' ____ ____
' | __ ) __ _ / ___|___ _ __
' | _ \ / _` | | / _ \| '_ \
' | |_) | (_| | |__| (_) | | | | --= A BaCon GUI BASIC-to-C converter =--
' |____/ \__,_|\____\___/|_| |_|
'
' Peter van Eerten - March 2009/May 2012. License: GPL version 3.
'
'----------------------------------------------------------------------------------------------
' CREDITS:
' - James C. Fuller for endless testing and patiently pointing to many issues
' - John Spikowksi for giving some hints to improve the language
' - Vovchik for providing ideas, programs and hints
' - Markus Vedder for testing bacongui and feedback
'
'----------------------------------------------------------------------------------------------
'
' 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.
'
' Terminal execution string suggestions ('@' means the program and its arguments):
'
' (1) xterm -hold -sb -geometry 132x40 -e @
' (2) rxvt -geometry 132x40 -e /bin/bash -c '@; read'
' (3) gnome-terminal --geometry 132x40 -e "/bin/bash -c '@; read'"
' (4) konsole --noclose --vt_sz 80x25 -e @
' (5) MacOSX: mrxvt -hold 1 -e @
' (6) MacOSX: open @
'
'----------------------------------------------------------------------------------------------
' GLOBAL INITIALIZATIONS
'----------------------------------------------------------------------------------------------
TRAP LOCAL
' Lower bound of array starts with 1
OPTION BASE 1
' Prevent parse errors
OPTION COLLAPSE TRUE
' Set socket timeout to 1 second
OPTION SOCKET 1
' We will be using memory streams
OPTION MEMSTREAM TRUE
' Version of BACON
CONST g_VERSION$ = "1.0 build 26"
' Version of documentation
CONST g_DOC$ = CONCAT$(GETENVIRON$("HOME"), "/.bacon/documentation26.html")
' Global to define '$'-replacement
CONST g_STRINGSIGN$ = "__b2c__string_var"
' Global BaCon shell temp file definition
CONST g_BACONSHELL$ = "/baconshell.bac"
'------------------------------------------------------------------------------------------------------------
' Where to put the syntaxfile
CONST Config_Path$ = "/.local/share/gtksourceview-3.0/language-specs"
CONST GDK_SHIFT_MASK = 1 << 0
CONST GDK_CONTROL_MASK = 1 << 2
CONST GTK_RESPONSE_ACCEPT = -3
CONST GTK_RESPONSE_OK = -5
CONST GTK_RESPONSE_CANCEL = -6
CONST GTK_RESPONSE_YES = -8
CONST GTK_RESPONSE_APPLY = -10
CONST GTK_WIN_POS_MOUSE = 2
CONST GTK_WIN_POS_CENTER_ON_PARENT = 4
CONST GTK_DIALOG_DESTROY_WITH_PARENT = 2
CONST GTK_MESSAGE_INFO = 0
CONST GTK_MESSAGE_WARNING = 1
CONST GTK_MESSAGE_ERROR = 3
CONST GTK_BUTTONS_CLOSE = 2
CONST GTK_BUTTONS_YES_NO = 4
CONST GTK_WRAP_NONE = 0
CONST GTK_WRAP_WORD = 2
CONST GTK_STATE_NORMAL = 0
CONST GTK_ACCEL_VISIBLE = 1
CONST GTK_WINDOW_TOPLEVEL = 0
CONST GTK_POLICY_AUTOMATIC = 1
CONST GTK_SHADOW_ETCHED_IN = 3
CONST GTK_ICON_SIZE_MENU = 1
CONST GTK_ICON_SIZE_DIALOG = 6
CONST GTK_RELIEF_NONE = 2
' Memory size for GtkIter
CONST DEFAULT_WIDGET_SIZE = 96
' The notebook can have maximum pages
CONST MAXPAGES = 100
CONST DEFTITLE$ = "BaCon GUI"
' Global ClipBoard object
DECLARE ClipBoard
' Hold widgets for the notebook
RECORD nbook[MAXPAGES]
LOCAL view, buffer, label, button, child
LOCAL title$
END RECORD
' Allow icons in buttons - for now intentionally commented as some Linux distros have issues with 'gconftool-2'
'IF LEN(EXEC$(CONCAT$("which gconftool-2 2>/dev/null"))) THEN SYSTEM "gconftool-2 --type boolean --set /desktop/gnome/interface/buttons_have_icons 1"
' Check if syntax file exists
IF NOT(FILEEXISTS(CONCAT$(GETENVIRON$("HOME"), Config_Path$, "/bacon.lang"))) THEN
PRINT "BaCon syntaxfile not found! Fetching from BaCon website... ";
IF Update_Syntaxfile(0) THEN
PRINT "done."
END IF
END IF
' Check if settings directory exists
IF NOT(FILEEXISTS(CONCAT$(GETENVIRON$("HOME"), "/.bacon/"))) THEN MAKEDIR CONCAT$(GETENVIRON$("HOME"), "/.bacon/")
CONST MAX_LIB_SEQ = 50
' Find libraries and import symbols
CALL Find_Gtk_Library
CALL Find_GtkSource_Library
CALL Find_Gdk_Library
CALL Find_Gobject_Library
CALL Find_Pango_Library
CALL Find_Gtkhtml_Library
CALL Find_Webkit_Library
' Do not forget to RESET the ERROR variable after all those erroneous IMPORT probing when running in TRAP LOCAL mode
ERROR = 0
' Run the GUI
CALL Build_Gui
'------------------------------------------------------------------------------------------------------------
' Let's get the GTK library
FUNCTION Find_Gtk_Library
LOCAL lib$
LOCAL sequence = -1
CATCH GOTO Redo_Import
IF INSTR(OS$, "Darwin") THEN
lib$ = "/opt/local/lib/libgtk-x11-2.0.0.dylib"
IF NOT(FILEEXISTS(lib$)) THEN
lib$ = "/Library/Frameworks/Gtk.framework/Libraries/libgtk-quartz-2.0.0.dylib"
END IF
END IF
LABEL Redo_Import
INCR sequence
IF sequence = MAX_LIB_SEQ THEN GOTO Print_Error
IF NOT(INSTR(lib$, "dylib")) THEN lib$ = CONCAT$("libgtk-3.so.", STR$(sequence))
IMPORT "gtk_init(int*,void*)" FROM lib$ TYPE void
IMPORT "gtk_accel_group_new" FROM lib$ TYPE long
IMPORT "gtk_box_pack_end(long,long,int,int,int)" FROM lib$ TYPE void
IMPORT "gtk_box_pack_start(long,long,int,int,int)" FROM lib$ TYPE void
IMPORT "gtk_button_new" FROM lib$ TYPE long
IMPORT "gtk_button_new_from_stock(char*)" FROM lib$ TYPE long
IMPORT "gtk_button_set_focus_on_click(long,int)" FROM lib$ TYPE void
IMPORT "gtk_button_set_relief(long,int)" FROM lib$ TYPE void
IMPORT "gtk_check_button_new_with_label(char*)" FROM lib$ TYPE long
IMPORT "gtk_check_menu_item_get_active(long)" FROM lib$ TYPE int
IMPORT "gtk_check_menu_item_set_active(long,int)" FROM lib$ TYPE void
IMPORT "gtk_check_menu_item_new_with_mnemonic(char*)" FROM lib$ TYPE long
IMPORT "gtk_check_version(int,int,int)" FROM lib$ TYPE char* ALIAS gtk_check_version$
IMPORT "gtk_clipboard_get(long)" FROM lib$ TYPE long
IMPORT "gtk_color_selection_dialog_new(char*)" FROM lib$ TYPE long
IMPORT "gtk_color_selection_get_current_color(long,long)" FROM lib$ TYPE void
IMPORT "gtk_color_selection_palette_from_string(char*,long,long)" FROM lib$ TYPE int
IMPORT "gtk_color_selection_palette_to_string(long,int)" FROM lib$ TYPE char*
IMPORT "gtk_color_selection_set_current_color(long,long)" FROM lib$ TYPE void
IMPORT "gtk_combo_box_text_append_text(long,char*)" FROM lib$ TYPE void
IMPORT "gtk_combo_box_text_get_active_text(long)" FROM lib$ TYPE char*
IMPORT "gtk_combo_box_text_new" FROM lib$ TYPE long
IMPORT "gtk_combo_box_set_active(long,int)" FROM lib$ TYPE void
IMPORT "gtk_container_add(long,long)" FROM lib$ TYPE void
IMPORT "gtk_container_set_border_width(long,int)" FROM lib$ TYPE void
IMPORT "gtk_dialog_run(long)" FROM lib$ TYPE int
IMPORT "gtk_dialog_set_default_response(long,int)" FROM lib$ TYPE void
IMPORT "gtk_entry_get_text(long)" FROM lib$ TYPE char*
IMPORT "gtk_entry_set_text(long,char*)" FROM lib$ TYPE void
IMPORT "gtk_entry_new" FROM lib$ TYPE long
IMPORT "gtk_events_pending" FROM lib$ TYPE int
IMPORT "gtk_file_chooser_add_filter(long,long)" FROM lib$ TYPE long
IMPORT "gtk_file_chooser_dialog_new(char*,long,int,char*,...)" FROM lib$ TYPE long
IMPORT "gtk_file_chooser_get_filename(long)" FROM lib$ TYPE char*
IMPORT "gtk_file_chooser_set_filename(long,char*)" FROM lib$ TYPE int
IMPORT "gtk_file_filter_add_pattern(long,char*)" FROM lib$ TYPE long
IMPORT "gtk_file_filter_new" FROM lib$ TYPE long
IMPORT "gtk_file_filter_set_name(long,char*)" FROM lib$ TYPE void
IMPORT "gtk_font_selection_dialog_get_font_name(long)" FROM lib$ TYPE char*
IMPORT "gtk_font_selection_dialog_new(char*)" FROM lib$ TYPE long
IMPORT "gtk_font_selection_dialog_set_font_name(long,char*)" FROM lib$ TYPE int
IMPORT "gtk_frame_new(char*)" FROM lib$ TYPE long
IMPORT "gtk_hbox_new(int,int)" FROM lib$ TYPE long
IMPORT "gtk_hseparator_new" FROM lib$ TYPE long
IMPORT "gtk_icon_size_lookup(int,long,long)" FROM lib$ TYPE int
IMPORT "gtk_image_new_from_stock(char*,int)" FROM lib$ TYPE long
IMPORT "gtk_label_new(char*)" FROM lib$ TYPE long
IMPORT "gtk_label_get_text(long)" FROM lib$ TYPE char*
IMPORT "gtk_label_set_text(long,char*)" FROM lib$ TYPE void
IMPORT "gtk_main" FROM lib$ TYPE void
IMPORT "gtk_main_iteration_do(int)" FROM lib$ TYPE int
IMPORT "gtk_menu_bar_new" FROM lib$ TYPE long
IMPORT "gtk_menu_item_new" FROM lib$ TYPE long
IMPORT "gtk_menu_item_new_with_mnemonic(char*)" FROM lib$ TYPE long
IMPORT "gtk_menu_item_new_with_label(char*)" FROM lib$ TYPE long
IMPORT "gtk_menu_item_set_submenu(long,long)" FROM lib$ TYPE void
IMPORT "gtk_menu_new" FROM lib$ TYPE long
IMPORT "gtk_menu_popup(long,long,long,void*,void*,int,int)" FROM lib$ TYPE void
IMPORT "gtk_menu_shell_append(long,long)" FROM lib$ TYPE void
IMPORT "gtk_message_dialog_new(long,int,int,int,char*,...)" FROM lib$ TYPE long
IMPORT "gtk_misc_set_alignment(long,float,float)" FROM lib$ TYPE void
IMPORT "gtk_notebook_append_page(long,long,long)" FROM lib$ TYPE int
IMPORT "gtk_notebook_get_tab_label_text(long,long)" FROM lib$ TYPE char*
IMPORT "gtk_notebook_get_current_page(long)" FROM lib$ TYPE int
IMPORT "gtk_notebook_get_n_pages(long)" FROM lib$ TYPE int
IMPORT "gtk_notebook_get_nth_page (long,int)" FROM lib$ TYPE long
IMPORT "gtk_notebook_new" FROM lib$ TYPE long
IMPORT "gtk_notebook_remove_page(long,int)" FROM lib$ TYPE void
IMPORT "gtk_notebook_get_tab_label_text(long,long)" FROM lib$ TYPE char*
IMPORT "gtk_notebook_set_current_page(long,int)" FROM lib$ TYPE void
IMPORT "gtk_notebook_set_scrollable(long,int)" FROM lib$ TYPE void
IMPORT "gtk_notebook_set_tab_reorderable(long,long,int)" FROM lib$ TYPE void
IMPORT "gtk_progress_bar_new" FROM lib$ TYPE long
IMPORT "gtk_progress_bar_set_fraction(long,double)" FROM lib$ TYPE void
IMPORT "gtk_progress_bar_set_text(long,char*)" FROM lib$ TYPE void
IMPORT "gtk_radio_button_new_with_label_from_widget(long,char*)" FROM lib$ TYPE long
IMPORT "gtk_rc_parse_string(char*)" FROM lib$ TYPE void
IMPORT "gtk_rc_reset_styles(long)" FROM lib$ TYPE void
IMPORT "gtk_scrolled_window_new(long,long)" FROM lib$ TYPE long
IMPORT "gtk_scrolled_window_set_policy(long,int,int)" FROM lib$ TYPE void
IMPORT "gtk_scrolled_window_set_shadow_type(long,int)" FROM lib$ TYPE void
IMPORT "gtk_settings_get_default" FROM lib$ TYPE long
IMPORT "gtk_show_about_dialog(long,char*,...)" FROM lib$ TYPE void
IMPORT "gtk_statusbar_get_context_id(long,char*)" FROM lib$ TYPE int
IMPORT "gtk_statusbar_new" FROM lib$ TYPE long
IMPORT "gtk_statusbar_pop(long,int)" FROM lib$ TYPE void
IMPORT "gtk_statusbar_push(long,int,char*)" FROM lib$ TYPE int
IMPORT "gtk_tearoff_menu_item_new(void)" FROM lib$ TYPE long
IMPORT "gtk_text_buffer_backspace(long,long,int,int)" FROM lib$ TYPE int
IMPORT "gtk_text_buffer_copy_clipboard(long,long)" FROM lib$ TYPE void
IMPORT "gtk_text_buffer_create_mark(long,char*,long,int)" FROM lib$ TYPE long
IMPORT "gtk_text_buffer_cut_clipboard(long,long,int)" FROM lib$ TYPE void
IMPORT "gtk_text_buffer_delete(long,long,long)" FROM lib$ TYPE void
IMPORT "gtk_text_buffer_delete_mark(long,long)" FROM lib$ TYPE void
IMPORT "gtk_text_buffer_get_bounds(long,long,long)" FROM lib$ TYPE void
IMPORT "gtk_text_buffer_get_end_iter(long,long)" FROM lib$ TYPE void
IMPORT "gtk_text_buffer_get_has_selection(long)" FROM lib$ TYPE int
IMPORT "gtk_text_buffer_get_insert(long)" FROM lib$ TYPE long
IMPORT "gtk_text_buffer_get_iter_at_line(long,long,int)" FROM lib$ TYPE void
IMPORT "gtk_text_buffer_get_iter_at_mark(long,long,long)" FROM lib$ TYPE void
IMPORT "gtk_text_buffer_get_line_count(long)" FROM lib$ TYPE int
IMPORT "gtk_text_buffer_get_selection_bound(long)" FROM lib$ TYPE long
IMPORT "gtk_text_buffer_get_selection_bounds(long,long,long)" FROM lib$ TYPE long
IMPORT "gtk_text_buffer_get_start_iter(long,long)" FROM lib$ TYPE void
IMPORT "gtk_text_buffer_get_text(long,long,long,int)" FROM lib$ TYPE char*
IMPORT "gtk_text_buffer_insert(long,long,char*,int)" FROM lib$ TYPE void
IMPORT "gtk_text_buffer_new(long)" FROM lib$ TYPE long
IMPORT "gtk_text_buffer_paste_clipboard(long,long,void*,int)" FROM lib$ TYPE void
IMPORT "gtk_text_buffer_place_cursor(long,long)" FROM lib$ TYPE void
IMPORT "gtk_text_buffer_select_range(long,long,long)" FROM lib$ TYPE void
IMPORT "gtk_text_buffer_set_text(long,char*,int)" FROM lib$ TYPE void
IMPORT "gtk_text_iter_forward_search(long,char*,int,long,long,void*)" FROM lib$ TYPE int
IMPORT "gtk_text_view_new_with_buffer(long)" FROM lib$ TYPE long
IMPORT "gtk_text_view_scroll_mark_onscreen(long,long)" FROM lib$ TYPE void
IMPORT "gtk_text_view_scroll_to_mark(long,long,double,int,double,double)" FROM lib$ TYPE void
IMPORT "gtk_text_view_set_editable(long,int)" FROM lib$ TYPE void
IMPORT "gtk_text_view_set_pixels_above_lines(long,int)" FROM lib$ TYPE void
IMPORT "gtk_text_view_set_wrap_mode(long,int)" FROM lib$ TYPE void
IMPORT "gtk_toggle_button_get_active(long)" FROM lib$ TYPE int
IMPORT "gtk_toggle_button_set_active(long,int)" FROM lib$ TYPE void
IMPORT "gtk_vbox_new(int,int)" FROM lib$ TYPE long
IMPORT "gtk_widget_add_accelerator(long,char*,long,int,int,int)" FROM lib$ TYPE void
IMPORT "gtk_widget_destroy(long)" FROM lib$ TYPE void
IMPORT "gtk_widget_grab_focus(long)" FROM lib$ TYPE void
IMPORT "gtk_widget_hide(long)" FROM lib$ TYPE void
IMPORT "gtk_widget_hide_on_delete(long)" FROM lib$ TYPE int
IMPORT "gtk_widget_modify_font(long,long)" FROM lib$ TYPE void
IMPORT "gtk_widget_set_name(long,char*)" FROM lib$ TYPE void
IMPORT "gtk_widget_set_sensitive(long,int)" FROM lib$ TYPE void
IMPORT "gtk_widget_set_size_request(long,int,int)" FROM lib$ TYPE void
IMPORT "gtk_widget_show_all(long)" FROM lib$ TYPE void
IMPORT "gtk_window_add_accel_group(long,long)" FROM lib$ TYPE void
IMPORT "gtk_window_get_title(long)" FROM lib$ TYPE char*
IMPORT "gtk_window_new(int)" FROM lib$ TYPE long
IMPORT "gtk_window_set_default_size(long,int,int)" FROM lib$ TYPE void
IMPORT "gtk_window_set_icon_name(long,char*)" FROM lib$ TYPE void
IMPORT "gtk_window_set_position(long,int)" FROM lib$ TYPE void
IMPORT "gtk_window_set_resizable(long,int)" FROM lib$ TYPE void
IMPORT "gtk_window_set_title(long,char*)" FROM lib$ TYPE void
IMPORT "gtk_window_set_transient_for(long,long)" FROM lib$ TYPE void
IMPORT "gtk_color_selection_dialog_get_color_selection(long)" FROM lib$ TYPE long
IMPORT "gtk_color_selection_get_current_rgba(long,long)" FROM lib$ TYPE void
IMPORT "gtk_widget_override_background_color(long,int,long)" FROM lib$ TYPE void
RETURN 0
LABEL Print_Error
PRINT "Gtk library not found!"
END
END FUNCTION
'------------------------------------------------------------------------------------------------------------
' Let's get the GtkSource library
FUNCTION Find_GtkSource_Library
LOCAL lib$
LOCAL sequence = -1
CATCH GOTO Redo_Import
IF INSTR(OS$, "Darwin") THEN
lib$ = "/opt/local/lib/libgtksourceview-2.0.0.dylib"
IF NOT(FILEEXISTS(lib$)) THEN
lib$ = "/Library/Frameworks/Gtk.framework/Libraries/libgtksourceview-2.0.0.dylib"
END IF
END IF
LABEL Redo_Import
INCR sequence
IF sequence = MAX_LIB_SEQ THEN GOTO Print_Error
IF NOT(INSTR(lib$, "dylib")) THEN lib$ = CONCAT$("libgtksourceview-3.0.so.", STR$(sequence))
IMPORT "gtk_source_buffer_new_with_language(long)" FROM lib$ TYPE long
IMPORT "gtk_source_buffer_can_redo(long)" FROM lib$ TYPE int
IMPORT "gtk_source_buffer_can_undo(long)" FROM lib$ TYPE int
IMPORT "gtk_source_buffer_set_highlight_matching_brackets(long,int)" FROM lib$ TYPE void
IMPORT "gtk_source_buffer_redo(long)" FROM lib$ TYPE void
IMPORT "gtk_source_buffer_undo(long)" FROM lib$ TYPE void
IMPORT "gtk_source_language_manager_get_default" FROM lib$ TYPE long
IMPORT "gtk_source_language_manager_get_language(long,char*)" FROM lib$ TYPE long
IMPORT "gtk_source_view_new_with_buffer(long)" FROM lib$ TYPE long
IMPORT "gtk_source_view_set_auto_indent(long,int)" FROM lib$ TYPE void
IMPORT "gtk_source_view_get_highlight_current_line(long)" FROM lib$ TYPE int
IMPORT "gtk_source_view_set_highlight_current_line(long,int)" FROM lib$ TYPE void
IMPORT "gtk_source_view_set_show_line_numbers(long,int)" FROM lib$ TYPE void
IMPORT "gtk_source_view_set_tab_width(long,int)" FROM lib$ TYPE void
RETURN 0
LABEL Print_Error
PRINT "Gtksourceview library not found!"
END
END FUNCTION
'------------------------------------------------------------------------------------------------------------
' Let's get the Gdk library
FUNCTION Find_Gdk_Library
LOCAL lib$
LOCAL sequence = -1
CATCH GOTO Redo_Import
IF INSTR(OS$, "Darwin") THEN
lib$ = "/opt/local/lib/libgdk-x11-2.0.0.dylib"
IF NOT(FILEEXISTS(lib$)) THEN
lib$ = "/Library/Frameworks/Gtk.framework/Libraries/libgdk-quartz-2.0.0.dylib"
END IF
END IF
LABEL Redo_Import
INCR sequence
IF sequence = MAX_LIB_SEQ THEN GOTO Print_Error
IF NOT(INSTR(lib$, "dylib")) THEN lib$ = CONCAT$("libgdk-3.so.", STR$(sequence))
IMPORT "gdk_atom_intern(char*,int)" FROM lib$ TYPE long
IMPORT "gdk_keyval_from_name(char*)" FROM lib$ TYPE int
IMPORT "gdk_window_at_pointer(long,long)" FROM lib$ TYPE long
IMPORT "gdk_window_get_pointer(long,long,long,long)" FROM lib$ TYPE long
RETURN 0
LABEL Print_Error
PRINT "Gdk library not found!"
END
END FUNCTION
'------------------------------------------------------------------------------------------------------------
' Let's get the GtkObject library
FUNCTION Find_Gobject_Library
LOCAL lib$
LOCAL sequence = -1
CATCH GOTO Redo_Import
IF INSTR(OS$, "Darwin") THEN
lib$ = "/opt/local/lib/libgobject-2.0.0.dylib"
IF NOT(FILEEXISTS(lib$)) THEN
lib$ = "/Library/Frameworks/Glib.framework/Libraries/libgobject-2.0.0.dylib"
END IF
END IF
LABEL Redo_Import
INCR sequence
IF sequence = MAX_LIB_SEQ THEN GOTO Print_Error
IF NOT(INSTR(lib$, "dylib")) THEN lib$ = CONCAT$("libgobject-2.0.so.", STR$(sequence))
IMPORT "g_signal_connect_data(long,char*,void*,long,long,int)" FROM lib$ TYPE void
IMPORT "g_object_set(long,char*,...)" FROM lib$ TYPE void
RETURN 0
LABEL Print_Error
PRINT "Gobject library not found!"
END
END FUNCTION
'------------------------------------------------------------------------------------------------------------
' Let's get the Pango library
FUNCTION Find_Pango_Library
LOCAL lib$
LOCAL sequence = -1
CATCH GOTO Redo_Import
IF INSTR(OS$, "Darwin") THEN
lib$ = "/opt/local/lib/libpango-1.0.0.dylib"
IF NOT(FILEEXISTS(lib$)) THEN
lib$ = "/Library/Frameworks/Gtk.framework/Libraries/libpango-1.0.0.dylib"
END IF
END IF
LABEL Redo_Import
INCR sequence
IF sequence = MAX_LIB_SEQ THEN GOTO Print_Error
IF NOT(INSTR(lib$, "dylib")) THEN lib$ = CONCAT$("libpango-1.0.so.", STR$(sequence))
IMPORT "pango_font_description_from_string(char*)" FROM lib$ TYPE long
IMPORT "pango_font_description_free(long)" FROM lib$ TYPE void
RETURN 0
LABEL Print_Error
PRINT "Pango library not found!"
END
END FUNCTION
'------------------------------------------------------------------------------------------------------------
' Let's get the Gtkhtml library
FUNCTION Find_Gtkhtml_Library
LOCAL lib$
LOCAL sequence = -1
LOCAL minor = 0
CATCH GOTO Redo_Import
g_LIBGTKHTML = 1
IF INSTR(OS$, "Darwin") THEN lib$ = "/opt/local/lib/libgtkhtml-2.0.0.0.dylib"
LABEL Redo_Import
INCR sequence
IF sequence = MAX_LIB_SEQ THEN
sequence = 0
INCR minor
IF minor > MAX_LIB_SEQ THEN GOTO Print_Error
END IF
IF NOT(INSTR(lib$, "dylib")) THEN lib$ = CONCAT$("libgtkhtml-3.", STR$(minor), ".so.", STR$(sequence))
IMPORT "gtk_html_new" FROM lib$ TYPE long
IMPORT "gtk_html_load_from_string(long,char*,int)" FROM lib$ TYPE void
RETURN 0
LABEL Print_Error
g_LIBGTKHTML = 0
END FUNCTION
'------------------------------------------------------------------------------------------------------------
' Let's get the Webkit library
FUNCTION Find_Webkit_Library
LOCAL lib$
LOCAL sequence = -1
CATCH GOTO Redo_Import
g_LIBGTKWEBKIT = 1
IF INSTR(OS$, "Darwin") THEN
lib$ = "/opt/local/lib/libwebkitgtk-1.0.dylib"
IF NOT(FILEEXISTS(lib$)) THEN
lib$ = "/Library/Frameworks/Gtk.framework/Libraries/libwebkitgtk-quartz-1.0.dylib"
END IF
END IF
LABEL Redo_Import
INCR sequence
IF sequence = MAX_LIB_SEQ THEN GOTO Print_Error
IF NOT(INSTR(lib$, "dylib")) THEN lib$ = CONCAT$("libwebkitgtk-3.0.so.", STR$(sequence))
IMPORT "webkit_web_view_new(void)" FROM lib$ TYPE long
IMPORT "webkit_web_view_load_uri(long,char*)" FROM lib$ TYPE void
IMPORT "webkit_web_settings_new(void)" FROM lib$ TYPE long
IMPORT "webkit_web_view_set_settings(long,long)" FROM lib$ TYPE void
RETURN 0
LABEL Print_Error
g_LIBGTKWEBKIT = 0
END FUNCTION
'------------------------------------------------------------------------------------------------------------
FUNCTION Update_Syntaxfile(NUMBER use_gui)
LOCAL dat$, total$, home$
LOCAL bacon, dialog
LOCAL syntaxfile TYPE FILE*
' Update GUI
IF use_gui THEN CALL SYNC
home$ = GETENVIRON$("HOME")
' Fetch the latest syntaxfile
CALL Download_File$("http://www.basic-converter.org/bacon.lang", use_gui) TO total$
IF LEN(total$) > 0 THEN
' Create directories
MAKEDIR CONCAT$(home$, Config_Path$)
' Save syntax file from BaCon website to correct location
OPEN CONCAT$(home$, Config_Path$, "/bacon.lang") FOR WRITING AS syntaxfile
WRITELN MID$(total$, INSTR(total$, " 0 THEN WRITELN "file ", nbook[x].title$ TO settings
NEXT
END IF
CLOSE FILE settings
END SUB
'------------------------------------------------------------------------------------------------------------
FUNCTION Get_Contents$
LOCAL iter1, iter2, page
LOCAL text$
iter1 = MEMORY(DEFAULT_WIDGET_SIZE)
iter2 = MEMORY(DEFAULT_WIDGET_SIZE)
page = gtk_notebook_get_current_page(g_Notebook)
gtk_text_buffer_get_bounds(nbook[page].buffer, iter1, iter2)
text$ = gtk_text_buffer_get_text(nbook[page].buffer, iter1, iter2, 1)
FREE iter1
FREE iter2
RETURN text$
END FUNCTION
'------------------------------------------------------------------------------------------------------------
' Update statusbar with message
SUB Statusbar_Msg(STRING txt)
gtk_statusbar_pop(g_Statusbar, g_Msgcid)
gtk_statusbar_push(g_Statusbar, g_Msgcid, txt)
END SUB
'------------------------------------------------------------------------------------------------------------
' Callback for OPEN file
SUB Open_File
LOCAL page
LOCAL title$
page = gtk_notebook_get_current_page(g_Notebook)
IF page >= 0 THEN
title$ = gtk_label_get_text(nbook[page].label)
IF EQUAL(LEFT$(title$, 1), "*") AND NOT(g_OPEN_PAGE) THEN
IF Run_Dialog(GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, CONCAT$("Save program '", MID$(title$, 3), "' ?"), -1) IS GTK_RESPONSE_YES THEN
CALL Save_File
END IF
END IF
END IF
gtk_widget_show_all(g_File_dialog)
END SUB
'------------------------------------------------------------------------------------------------------------
' Callback for OPEN URL
SUB Handle_Open_Url
LOCAL page
LOCAL title$, doc$
gtk_widget_hide(g_Url_dialog)
page = gtk_notebook_get_current_page(g_Notebook)
title$ = gtk_label_get_text(nbook[page].label)
doc$ = Download_File$(gtk_entry_get_text(g_Url_entry), TRUE)
IF LEN(doc$) > 0 THEN
IF EQUAL(LEFT$(title$, 1), "*") AND NOT(g_OPEN_PAGE) THEN
IF Run_Dialog(GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, CONCAT$("Save program '", MID$(title$, 3), "' ?"), -1) IS GTK_RESPONSE_YES THEN
CALL Save_File
END IF
END IF
CALL Load_File(doc$, FALSE)
title$ = gtk_entry_get_text(g_Url_entry)
gtk_label_set_text(nbook[page].label, MID$(title$, INSTRREV(title$, "/")+1) )
CALL Set_Changed
nbook[page].title$ = MID$(title$, INSTRREV(title$, "/")+1)
END IF
END SUB
'------------------------------------------------------------------------------------------------------------
' Callback to hide a widget from "clicked" signal
SUB Hide_Dialog(NUMBER widget, NUMBER dialog)
gtk_widget_hide(dialog)
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Load_File(STRING name$, NUMBER as_file)
LOCAL buffer, filelen, iter, page
LOCAL str$
iter = MEMORY(DEFAULT_WIDGET_SIZE)
' Get current page
page = gtk_notebook_get_current_page(g_Notebook)
IF as_file THEN
filelen = FILELEN(name$)
buffer = MEMORY(filelen)
OPEN name$ FOR READING AS fh
GETBYTE buffer FROM fh SIZE filelen
CLOSE FILE fh
OPEN buffer FOR MEMORY AS str$
gtk_text_buffer_set_text(nbook[page].buffer, str$, -1)
CLOSE MEMORY str$
FREE buffer
' Remove last CR from buffer
gtk_text_buffer_get_end_iter(nbook[page].buffer, iter)
gtk_text_buffer_backspace(nbook[page].buffer, iter, 0, 1)
gtk_label_set_text(nbook[page].label, MID$(name$, INSTRREV(name$, "/")+1) )
nbook[page].title$ = name$
Statusbar_Msg(CONCAT$("File '", name$, "' loaded successfully."))
ELSE
gtk_text_buffer_set_text(nbook[page].buffer, name$, -1)
' Remove last CR from buffer
gtk_text_buffer_get_end_iter(nbook[page].buffer, iter)
gtk_text_buffer_backspace(nbook[page].buffer, iter, 0, 1)
gtk_label_set_text(nbook[page].label, "* New" )
nbook[page].title$ = ""
Statusbar_Msg("Data loaded successfully.")
END IF
' Put cursor to the beginning of the file
gtk_text_buffer_get_start_iter(nbook[page].buffer, iter)
gtk_text_buffer_place_cursor(nbook[page].buffer, iter)
FREE iter
END SUB
'------------------------------------------------------------------------------------------------------------
' Handle dialog actions
SUB Handle_Open_Dialog(NUMBER widget, int action)
LOCAL name TYPE STRING
LOCAL response
IF action IS GTK_RESPONSE_ACCEPT THEN
gtk_widget_hide(g_File_dialog)
name = gtk_file_chooser_get_filename(g_File_dialog)
IF g_OPEN_PAGE THEN
CALL Create_Page
g_OPEN_PAGE = FALSE
END IF
Load_File(name, TRUE)
FREE name
ELIF action IS GTK_RESPONSE_APPLY THEN
name = gtk_file_chooser_get_filename(g_File_dialog)
response = Run_Dialog(GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, CONCAT$("Delete file '", name, "'?"), -1)
IF response IS GTK_RESPONSE_YES THEN
DELETE FILE name
END IF
FREE name
ELSE
gtk_widget_hide(g_File_dialog)
END IF
END SUB
'------------------------------------------------------------------------------------------------------------
' Callback for SAVE file
SUB Save_File
LOCAL page, response
page = gtk_notebook_get_current_page(g_Notebook)
IF LEN(nbook[page].title$) > 0 THEN
OPEN nbook[page].title$ FOR WRITING AS sourcefile
WRITELN Get_Contents$() TO sourcefile
CLOSE FILE sourcefile
gtk_label_set_text(nbook[page].label, MID$(nbook[page].title$, INSTRREV(nbook[page].title$, "/")+1) )
Statusbar_Msg(CONCAT$("Current code saved to '", nbook[page].title$, "'."))
ELSE
response = gtk_dialog_run(g_Save_dialog)
END IF
END SUB
'------------------------------------------------------------------------------------------------------------
' Callback for SAVE AS
SUB Save_Fileas
LOCAL page
LOCAL title$
page = gtk_notebook_get_current_page(g_Notebook)
IF LEN(nbook[page].title$) > 0 THEN
IF LEFT$(nbook[page].title$, 2) = "* " THEN
title$ = MID$(nbook[page].title$, 3)
ELSE
title$ = nbook[page].title$
END IF
gtk_file_chooser_set_filename(g_Save_dialog, title$)
END IF
gtk_widget_show_all(g_Save_dialog)
END SUB
'------------------------------------------------------------------------------------------------------------
' Handle SAVE AS dialog actions
SUB Handle_Save_Dialog(NUMBER widget, int action)
LOCAL page
LOCAL response TYPE int
' Define by reference
LOCAL name TYPE STRING
gtk_widget_hide(g_Save_dialog)
IF action IS GTK_RESPONSE_ACCEPT THEN
name = gtk_file_chooser_get_filename(widget)
IF FILEEXISTS(name) THEN
response = Run_Dialog(GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, CONCAT$("Overwrite existing '", MID$(name, INSTRREV(name, "/")+1), "'?"), -1)
ELSE
response = GTK_RESPONSE_YES
END IF
IF response IS GTK_RESPONSE_YES THEN
OPEN name FOR WRITING AS sourcefile
WRITELN Get_Contents$() TO sourcefile
CLOSE FILE sourcefile
page = gtk_notebook_get_current_page(g_Notebook)
gtk_label_set_text(nbook[page].label, MID$(name, INSTRREV(name, "/")+1) )
Statusbar_Msg(CONCAT$("Current code saved to '", name, "'."))
nbook[page].title$ = name
ELSE
Statusbar_Msg(CONCAT$("Save cancelled."))
END IF
END IF
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Set_Indent
LOCAL x
FOR x = 0 TO gtk_notebook_get_n_pages(g_Notebook)-1
gtk_source_view_set_auto_indent(nbook[x].view, gtk_check_menu_item_get_active(indent_menu))
NEXT
Save_Defaults(FALSE)
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Set_Linenr
LOCAL x
FOR x = 0 TO gtk_notebook_get_n_pages(g_Notebook)-1
gtk_source_view_set_show_line_numbers(nbook[x].view, gtk_check_menu_item_get_active(linenr_menu))
NEXT
Save_Defaults(FALSE)
END SUB
'------------------------------------------------------------------------------------------------------------
' At each keystroke set title to 'changed'
SUB Set_Changed
LOCAL title$
LOCAL page
page = gtk_notebook_get_current_page(g_Notebook)
title$ = gtk_label_get_text(nbook[page].label)
IF NOT(EQUAL(LEFT$(title$, 1), "*")) THEN
gtk_label_set_text(nbook[page].label, CONCAT$("* ", title$) )
END IF
END SUB
'------------------------------------------------------------------------------------------------------------
FUNCTION Cursor_Changed
LOCAL view
view = nbook[gtk_notebook_get_current_page(g_Notebook)].view
IF gtk_source_view_get_highlight_current_line(view) THEN gtk_source_view_set_highlight_current_line(view, 0)
RETURN FALSE
END FUNCTION
'------------------------------------------------------------------------------------------------------------
SUB Set_Wrapmode
LOCAL x
IF gtk_check_menu_item_get_active(wrap_menu) THEN
FOR x = 0 TO gtk_notebook_get_n_pages(g_Notebook)-1
gtk_text_view_set_wrap_mode(nbook[x].view, GTK_WRAP_WORD)
NEXT
ELSE
FOR x = 0 TO gtk_notebook_get_n_pages(g_Notebook)-1
gtk_text_view_set_wrap_mode(nbook[x].view, GTK_WRAP_NONE)
NEXT
ENDIF
Save_Defaults(FALSE)
END SUB
'------------------------------------------------------------------------------------------------------------
' Handle FONT selection
SUB Handle_Font_Dialog(NUMBER widget, int action)
LOCAL name TYPE STRING
LOCAL desc, x
IF action = GTK_RESPONSE_CANCEL OR action = GTK_RESPONSE_OK THEN gtk_widget_hide(g_Font_dialog)
IF action IS GTK_RESPONSE_OK OR action IS GTK_RESPONSE_APPLY THEN
name = gtk_font_selection_dialog_get_font_name(g_Font_dialog)
desc = pango_font_description_from_string(name)
FOR x = 0 TO gtk_notebook_get_n_pages(g_Notebook)-1
gtk_widget_modify_font(nbook[x].view, desc)
NEXT
pango_font_description_free(desc)
Statusbar_Msg(CONCAT$("Font has been changed to '", name, "'."))
Save_Defaults(FALSE)
END IF
END SUB
'------------------------------------------------------------------------------------------------------------
' Handle COLOR selection
SUB Handle_Color_Dialog(NUMBER widget, int action)
LOCAL colselect, gdkrgba, npage
gtk_widget_hide(g_Color_dialog)
IF action IS GTK_RESPONSE_OK THEN
colselect = gtk_color_selection_dialog_get_color_selection(g_Color_dialog)
gdkrgba = MEMORY(DEFAULT_WIDGET_SIZE)
gtk_color_selection_get_current_rgba(colselect, gdkrgba)
FOR npage = 0 TO gtk_notebook_get_n_pages(g_Notebook)-1
gtk_widget_override_background_color(nbook[npage].view, 0, gdkrgba)
NEXT
Statusbar_Msg("Color was successfully changed.")
FREE gdkrgba
Save_Defaults(FALSE)
END IF
END SUB
'------------------------------------------------------------------------------------------------------------
' Handle PRINT selection
SUB Handle_Print_Dialog(NUMBER widget)
LOCAL page
LOCAL command$
gtk_widget_hide(g_Print_dialog)
page = gtk_notebook_get_current_page(g_Notebook)
command$ = gtk_combo_box_text_get_active_text(g_Print_combo)
IF LEN(command$) = 0 OR command$ = "No printing system found" OR ISFALSE(LEN(EXEC$(CONCAT$("which lp 2>/dev/null")))) THEN
CALL Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Unable to print document!\n\nNo printing system available.", -1)
ELSE
IF gtk_toggle_button_get_active(g_Print_check2) THEN command$ = CONCAT$(command$, " -o landscape")
IF gtk_toggle_button_get_active(g_Print_check4) THEN command$ = CONCAT$(command$, " -o sides=two-sided-long-edge")
SYSTEM CONCAT$("lp -d ", command$, " ", nbook[page].title$)
END IF
END SUB
'------------------------------------------------------------------------------------------------------------
' Update syntax file
SUB Get_Syntax
IF Update_Syntaxfile(1) THEN CALL Run_Dialog(GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "The BaCon language file was updated successfully!\n\n\tRestart the GUI to activate the changes.", -1)
END SUB
'------------------------------------------------------------------------------------------------------------
' Info dialog
SUB Show_Info
gtk_show_about_dialog(g_Win, "program-name", DEFTITLE$, "version", g_VERSION$, "copyright", "(c) Peter van Eerten", \
"comments", "GUI version of BaCon using GtkSourceView 3.x.", "website", "http://www.basic-converter.org/", NULL)
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Cut_Text
LOCAL page
page = gtk_notebook_get_current_page(g_Notebook)
gtk_text_buffer_cut_clipboard(nbook[page].buffer, g_ClipBoard, 1)
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Copy_Text
LOCAL page
page = gtk_notebook_get_current_page(g_Notebook)
gtk_text_buffer_copy_clipboard(nbook[page].buffer, g_ClipBoard)
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Paste_Text
LOCAL page
page = gtk_notebook_get_current_page(g_Notebook)
gtk_text_buffer_paste_clipboard(nbook[page].buffer, g_ClipBoard, NULL, 1)
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Undo_Action
LOCAL page, mark
page = gtk_notebook_get_current_page(g_Notebook)
IF gtk_source_buffer_can_undo(nbook[page].buffer) THEN gtk_source_buffer_undo(nbook[page].buffer)
mark = gtk_text_buffer_get_insert(nbook[page].buffer)
gtk_text_view_scroll_mark_onscreen(nbook[page].view, mark)
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Redo_Action
LOCAL page, mark
page = gtk_notebook_get_current_page(g_Notebook)
IF gtk_source_buffer_can_redo(nbook[page].buffer) THEN gtk_source_buffer_redo(nbook[page].buffer)
mark = gtk_text_buffer_get_insert(nbook[page].buffer)
gtk_text_view_scroll_mark_onscreen(nbook[page].view, mark)
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Select_All
LOCAL page, start_iter, end_iter
start_iter = MEMORY(DEFAULT_WIDGET_SIZE)
end_iter = MEMORY(DEFAULT_WIDGET_SIZE)
page = gtk_notebook_get_current_page(g_Notebook)
gtk_text_buffer_get_bounds(nbook[page].buffer, start_iter, end_iter)
gtk_text_buffer_select_range(nbook[page].buffer, start_iter, end_iter)
FREE start_iter
FREE end_iter
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Close_Tab(NUMBER widget, NUMBER flag)
LOCAL title$
LOCAL page, x
IF flag THEN
FOR x = 0 TO gtk_notebook_get_n_pages(g_Notebook)-1
IF nbook[x].button = widget THEN
page = x
BREAK
END IF
NEXT
ELSE
page = gtk_notebook_get_current_page(g_Notebook)
END IF
IF page >= 0 THEN
title$ = gtk_label_get_text(nbook[page].label)
IF EQUAL(LEFT$(title$, 1), "*") THEN
IF Run_Dialog(GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, CONCAT$("Save program '", MID$(title$, 2), "' ?"), -1) IS GTK_RESPONSE_YES THEN
Save_File
END IF
END IF
gtk_notebook_remove_page(g_Notebook, page)
' Scroll record array
FOR x = page TO gtk_notebook_get_n_pages(g_Notebook)-1
nbook[x].view = nbook[x+1].view
nbook[x].buffer = nbook[x+1].buffer
nbook[x].label = nbook[x+1].label
nbook[x].button = nbook[x+1].button
nbook[x].child = nbook[x+1].child
nbook[x].title$ = nbook[x+1].title$
NEXT
END IF
' If there are no tabs, disable some of the menus
IF gtk_notebook_get_n_pages(g_Notebook) IS 0 THEN
gtk_widget_set_sensitive(file_menu, FALSE)
gtk_widget_set_sensitive(url_menu, FALSE)
gtk_widget_set_sensitive(save_menu, FALSE)
gtk_widget_set_sensitive(saveas_menu, FALSE)
gtk_widget_set_sensitive(print_menu, FALSE)
gtk_widget_set_sensitive(closetab_menu, FALSE)
gtk_widget_set_sensitive(cut_menu, FALSE)
gtk_widget_set_sensitive(copy_menu, FALSE)
gtk_widget_set_sensitive(paste_menu, FALSE)
gtk_widget_set_sensitive(select_menu, FALSE)
gtk_widget_set_sensitive(undo_menu, FALSE)
gtk_widget_set_sensitive(redo_menu, FALSE)
gtk_widget_set_sensitive(find_menu, FALSE)
gtk_widget_set_sensitive(indent_menu, FALSE)
gtk_widget_set_sensitive(linenr_menu, FALSE)
gtk_widget_set_sensitive(wrap_menu, FALSE)
gtk_widget_set_sensitive(page_menu, FALSE)
gtk_widget_set_sensitive(font_menu, FALSE)
gtk_widget_set_sensitive(color_menu, FALSE)
gtk_widget_set_sensitive(spacing_menu, FALSE)
gtk_widget_set_sensitive(conv_menu, FALSE)
gtk_widget_set_sensitive(exec_menu, FALSE)
gtk_widget_set_sensitive(test_menu, FALSE)
END IF
END SUB
'------------------------------------------------------------------------------------------------------------
' Callback for exit
SUB Exit_Prog
Save_Defaults(TRUE)
REPEAT
Close_Tab(0, 0)
UNTIL gtk_notebook_get_n_pages(g_Notebook) IS 0
' Use normal 'exit' as 'gtk_exit()' is deprecated
END
ENDSUB
'------------------------------------------------------------------------------------------------------------
SUB Create_Page
LOCAL lm, lang, buffer, view, scrolled, label, hbox, button, image, gtksettings, sc, pw, xicon, yicon
LOCAL page TYPE int
' Create language manager
lm = gtk_source_language_manager_get_default()
' Define language
lang = gtk_source_language_manager_get_language(lm, "bacon")
' Setup buffer and viewer using BaCon as language
buffer = gtk_source_buffer_new_with_language(lang)
g_signal_connect_data(buffer, "changed", Set_Changed, 0, 0, 0)
gtk_source_buffer_set_highlight_matching_brackets(buffer, 1)
view = gtk_source_view_new_with_buffer(buffer)
g_signal_connect_data(view, "key-press-event", Cursor_Changed, 0, 0, 0)
' Tab space to 4 characters
gtk_source_view_set_tab_width(view, 4)
' Create scrolled window
scrolled = gtk_scrolled_window_new(0, 0)
gtk_scrolled_window_set_policy(scrolled, 1, 1)
gtk_scrolled_window_set_shadow_type(scrolled, 3)
gtk_container_add(scrolled, view)
' Create the tab, a ridiculous amount of code needed for the 'x' on the tab
hbox = gtk_hbox_new(0, 10)
label = gtk_label_new("New ")
image = gtk_image_new_from_stock("gtk-close", GTK_ICON_SIZE_MENU)
gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, ADDRESS(xicon), ADDRESS(yicon))
button = gtk_button_new()
gtk_widget_set_name(button, STR$(button))
gtk_button_set_relief(button, GTK_RELIEF_NONE)
gtk_button_set_focus_on_click(button, FALSE)
gtk_widget_set_size_request(button, xicon, yicon)
gtk_container_add(button, image)
g_signal_connect_data(button, "clicked", Close_Tab, 1, 0, 0)
gtk_box_pack_start(hbox, label, 0, 0, 0)
gtk_box_pack_start(hbox, button, 0, 0, 0)
gtksettings = gtk_settings_get_default()
gtk_rc_parse_string("style \"baconstyle\" { xthickness = 0 }")
gtk_rc_parse_string("style \"baconstyle\" { ythickness = 0 }")
gtk_rc_parse_string(CONCAT$("widget \"*.*.", STR$(button), "*\" style \"baconstyle\""))
gtk_rc_reset_styles(gtksettings)
gtk_widget_show_all(hbox)
page = gtk_notebook_append_page(g_Notebook, scrolled, hbox)
' Set new tab as active
gtk_widget_show_all(g_Notebook)
gtk_notebook_set_current_page(g_Notebook, page)
gtk_notebook_set_tab_reorderable(g_Notebook, scrolled, TRUE)
' Store new widgets
nbook[page].view = view
nbook[page].buffer = buffer
nbook[page].label = label
nbook[page].button = button
nbook[page].child = scrolled
nbook[page].title$ = ""
IF gtk_notebook_get_n_pages(g_Notebook) IS 1 THEN
gtk_widget_set_sensitive(file_menu, TRUE)
gtk_widget_set_sensitive(url_menu, TRUE)
gtk_widget_set_sensitive(print_menu, TRUE)
gtk_widget_set_sensitive(save_menu, TRUE)
gtk_widget_set_sensitive(saveas_menu, TRUE)
gtk_widget_set_sensitive(closetab_menu, TRUE)
gtk_widget_set_sensitive(cut_menu, TRUE)
gtk_widget_set_sensitive(copy_menu, TRUE)
gtk_widget_set_sensitive(paste_menu, TRUE)
gtk_widget_set_sensitive(select_menu, TRUE)
gtk_widget_set_sensitive(undo_menu, TRUE)
gtk_widget_set_sensitive(redo_menu, TRUE)
gtk_widget_set_sensitive(find_menu, TRUE)
gtk_widget_set_sensitive(indent_menu, TRUE)
gtk_widget_set_sensitive(linenr_menu, TRUE)
gtk_widget_set_sensitive(wrap_menu, TRUE)
gtk_widget_set_sensitive(page_menu, TRUE)
gtk_widget_set_sensitive(font_menu, TRUE)
gtk_widget_set_sensitive(color_menu, TRUE)
gtk_widget_set_sensitive(spacing_menu, TRUE)
gtk_widget_set_sensitive(conv_menu, TRUE)
gtk_widget_set_sensitive(exec_menu, TRUE)
gtk_widget_set_sensitive(test_menu, TRUE)
END IF
gtk_widget_grab_focus(view)
' Get the default settings for the new page
Load_Defaults
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Reorder_Tabs
LOCAL x, y
RECORD tmpbook[MAXPAGES]
LOCAL view, buffer, label, child, button
LOCAL title$
END RECORD
' Make a copy
FOR x = 0 TO gtk_notebook_get_n_pages(g_Notebook)-1
tmpbook[x].view = nbook[x].view
tmpbook[x].buffer = nbook[x].buffer
tmpbook[x].label = nbook[x].label
tmpbook[x].button = nbook[x].button
tmpbook[x].child = nbook[x].child
tmpbook[x].title$ = nbook[x].title$
NEXT
' Check order
FOR x = 0 TO gtk_notebook_get_n_pages(g_Notebook)-1
FOR y = 0 TO gtk_notebook_get_n_pages(g_Notebook)-1
IF tmpbook[x].child IS gtk_notebook_get_nth_page(g_Notebook, y) THEN
nbook[y].view = tmpbook[x].view
nbook[y].buffer = tmpbook[x].buffer
nbook[y].label = tmpbook[x].label
nbook[y].button = tmpbook[x].button
nbook[y].child = tmpbook[x].child
nbook[y].title$ = tmpbook[x].title$
BREAK
END IF
NEXT
NEXT
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Open_Page
g_OPEN_PAGE = TRUE
Open_File
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Start_Find
gtk_widget_show_all(g_Find)
gtk_widget_grab_focus(g_Find_entry)
END SUB
'------------------------------------------------------------------------------------------------------------
' Action to find term and scroll text_view to that place
SUB Find_Term(NUMBER widget, NUMBER replace)
LOCAL iter, start_iter, end_iter, page, result, mark
LOCAL text$
text$ = gtk_entry_get_text(g_Find_entry)
page = gtk_notebook_get_current_page(g_Notebook)
iter = MEMORY(DEFAULT_WIDGET_SIZE)
start_iter = MEMORY(DEFAULT_WIDGET_SIZE)
end_iter = MEMORY(DEFAULT_WIDGET_SIZE)
' If there is a selection move cursor behind it
IF gtk_text_buffer_get_has_selection(nbook[page].buffer) THEN
' Replace action
IF replace THEN
gtk_text_buffer_get_selection_bounds(nbook[page].buffer, start_iter, end_iter)
gtk_text_buffer_delete(nbook[page].buffer, start_iter, end_iter)
gtk_text_buffer_insert(nbook[page].buffer, start_iter, gtk_entry_get_text(g_Repl_entry), -1)
ELSE
mark = gtk_text_buffer_get_selection_bound(nbook[page].buffer)
gtk_text_buffer_get_iter_at_mark(nbook[page].buffer, iter, mark)
gtk_text_buffer_place_cursor(nbook[page].buffer, iter)
END IF
END IF
LABEL repeat
mark = gtk_text_buffer_get_insert(nbook[page].buffer)
gtk_text_buffer_get_iter_at_mark(nbook[page].buffer, iter, mark)
result = gtk_text_iter_forward_search(iter, text$, 0, start_iter, end_iter, NULL)
IF NOT(result) THEN
IF Run_Dialog(GTK_MESSAGE_INFO, GTK_BUTTONS_YES_NO, CONCAT$(NL$, "Term '", text$, "' not found! Restart from top?"), -1) IS GTK_RESPONSE_YES THEN
gtk_text_buffer_get_start_iter(nbook[page].buffer, iter)
gtk_text_buffer_place_cursor(nbook[page].buffer, iter)
GOTO repeat
END IF
ELSE
' Find action
gtk_text_buffer_select_range(nbook[page].buffer, start_iter, end_iter)
mark = gtk_text_buffer_get_selection_bound(nbook[page].buffer)
gtk_text_view_scroll_to_mark(nbook[page].view, mark, 0, 1, 0.5, 0.5)
END IF
FREE iter
FREE start_iter
FREE end_iter
END SUB
'------------------------------------------------------------------------------------------------------------
FUNCTION Show_Popup
LOCAL gdkwin, mask
LOCAL x, y TYPE int
gdkwin = gdk_window_at_pointer(ADDRESS(x), ADDRESS(y))
gdk_window_get_pointer(gdkwin, ADDRESS(x), ADDRESS(y), ADDRESS(mask))
' Only right mouse button should activate popup
IF (mask & (1 << 10)) THEN
gtk_menu_popup(g_Cmenu, 0, 0, NULL, NULL, 3, 0)
RETURN TRUE
END IF
' If other button is pressed, resume default event handling
RETURN FALSE
END FUNCTION
'------------------------------------------------------------------------------------------------------------
SUB Show_Dialog(NUMBER widget, NUMBER data)
gtk_widget_show_all(data)
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Handle_Help
LOCAL total$, tmp$, browser$
LOCAL doc TYPE FILE*
LOCAL data
' Get environment variable or use MacOSX
IF INSTR(OS$, "Darwin") THEN
browser$ = "open -a Safari"
ELSE
browser$ = GETENVIRON$("DEFAULTBROWSER")
END IF
' Only fetch documentation if we have means to look at it
IF g_LIBGTKHTML OR g_LIBGTKWEBKIT OR LEN(EXEC$(CONCAT$("which ", browser$, " 2>/dev/null"))) OR LEN(EXEC$("which firefox 2>/dev/null")) THEN
' Check if cached documentation exists, if not get it
IF NOT(FILEEXISTS(g_DOC$)) THEN
total$ = Download_File$("http://www.basic-converter.org/documentation.html", TRUE)
' Save documentation
IF LEN(total$) > 0 THEN
OPEN g_DOC$ FOR WRITING AS doc
WRITELN REPLACE$(total$, "
If the pop-up is blocked, click here for the BaCon Documentation Navigator
", "") TO doc
CLOSE FILE doc
END IF
END IF
' Choose HTML renderer
IF LEN(EXEC$(CONCAT$("which ", browser$, " 2>/dev/null"))) THEN
SYSTEM CONCAT$(browser$, " ", g_DOC$, " &")
ELIF g_LIBGTKWEBKIT THEN
webkit_web_view_load_uri(g_Html_widget, CONCAT$("file://", g_DOC$))
gtk_widget_show_all(g_Html)
CALL SYNC
ELIF g_LIBGTKHTML THEN
data = MEMORY(FILELEN(g_DOC$))
OPEN g_DOC$ FOR READING AS doc
GETBYTE data FROM doc SIZE FILELEN(g_DOC$)
CLOSE FILE doc
OPEN data FOR MEMORY AS tmp$
total$ = tmp$
CLOSE MEMORY tmp$
gtk_html_load_from_string(g_Html_widget, total$, -1)
gtk_widget_show_all(g_Html)
CALL SYNC
FREE data
ELSE
IF INSTR(OS$, "Darwin") THEN
SYSTEM CONCAT$(browser$, " ", g_DOC$)
ELSE
SYSTEM CONCAT$("firefox -new-tab ", g_DOC$)
END IF
END IF
ELSE
CALL Run_Dialog(GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, "Unable to display BaCon help! Please set the environment variable DEFAULTBROWSER to a valid HTML viewer.", -1)
END IF
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Set_Spacing(NUMBER widget, int height)
LOCAL x
FOR x = 0 TO gtk_notebook_get_n_pages(g_Notebook)-1
gtk_text_view_set_pixels_above_lines(nbook[x].view, height)
NEXT
END SUB
'----------------------------------------------------------------------------------------------
' Download a file like "http://www.basic-converter.org/prog.bac"
FUNCTION Download_File$(STRING name$, NUMBER use_gui)
LOCAL total$, dat$
LOCAL mynet
LOCAL recdata, size, length TYPE FLOATING
LOCAL baconfile TYPE FILE*
CATCH GOTO network_error
' Rip off HTTP protocol name if it is there
IF LEFT$(CHOP$(name$), 7) = "http://" THEN name$ = MID$(CHOP$(name$), 8)
' Open HTTP connection on port 80
OPEN CONCAT$(LEFT$(name$, INSTR(name$, "/")-1), ":80") FOR NETWORK AS mynet
SEND CONCAT$("GET /", MID$(name$, INSTR(name$, "/")+1), " HTTP/1.1\r\nHost: ", LEFT$(name$, INSTR(name$, "/")-1), "\r\n\r\n") TO mynet
' Set progress dialog
IF use_gui THEN
gtk_window_set_title(g_Progress, MID$(name$, INSTRREV(name$, "/")+1))
gtk_progress_bar_set_fraction(g_Progressbar, 0.0)
gtk_widget_show_all(g_Progress): CALL SYNC
END IF
RECEIVE dat$ FROM mynet CHUNK 1024 SIZE size
' Get the filesize from the HTTP header
IF NOT(INSTR(dat$, "Content-Length:")) THEN
IF use_gui THEN
CALL Run_Dialog(GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: file '", name$, "' not found! Check URL and try again."), -1)
ELSE
PRINT "ERROR: file '", name$, "' not found! Check URL and try again."
END IF
GOTO finish
END IF
dat$ = MID$(dat$, INSTR(dat$, "Content-Length:")+15)
length = VAL(LEFT$(dat$, INSTR(dat$, NL$)))
' As long as there is data, get it
WHILE WAIT(mynet, 1000)
total$ = CONCAT$(total$, dat$)
IF use_gui THEN
' Update progressbar
INCR recdata, size
gtk_progress_bar_set_text(g_Progressbar, CONCAT$( STR$(INT(recdata/length*100.0) ), "%") )
IF recdata <= length THEN gtk_progress_bar_set_fraction(g_Progressbar, (double)recdata/length)
CALL SYNC
END IF
RECEIVE dat$ FROM mynet CHUNK 1024 SIZE size
IF LEN(dat$) = 0 THEN BREAK
WEND
CLOSE NETWORK mynet
IF use_gui THEN
gtk_widget_hide(g_Progress)
CALL SYNC
END IF
' Attach last data and rip off HTTP headers
total$ = CONCAT$( MID$(total$, INSTR(total$, "\r\n\r\n")+4), dat$)
' Check amount of data
IF LEN(total$) != length THEN
IF use_gui THEN
CALL Run_Dialog(GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, CONCAT$("WARNING: file http://'", name$, "' could not be downloaded. Try again later."), -1)
ELSE
PRINT "WARNING: file http://'", name$, "' could not be downloaded. Try again later."
END IF
total$ = ""
END IF
LABEL finish
RETURN total$
' Something happened in setting up the connection
LABEL network_error
IF use_gui THEN
CALL Run_Dialog(GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: the site http://'", LEFT$(name$, INSTR(name$, "/")-1), ", is not reachable! Try again later."), -1)
ELSE
PRINT "ERROR: the site http://'", LEFT$(name$, INSTR(name$, "/")-1), ", is not reachable! Try again later."
END IF
CATCH RESET
RETURN ""
END FUNCTION
'------------------------------------------------------------------------------------------------------------
SUB Build_Gui
LOCAL bacamount, x, size, sep1, sep2, sep3, sep4, sep5, sep6, sep7, sep8, sep9, sep10, sep11, sep12, sep13, sep14, sep15, sep16
LOCAL menubar, fmenu, ftear, fmenu_item, emenu, etear, emenu_item, omenu, otear, omenu_item, comenu, cotear, comenu_item, hmenu, htear, hmenu_item
LOCAL options_vbox, options_hbox1, options_hbox2, options_hbox3, options_hbox4, options_hbox5, options_hbox6
LOCAL options_cancel, options_close, compiler_label, flags_label, options_label, inc_label, tmpdir_label, url_label, url_cancel, url_load, url_vbox, url_hbox1, url_hbox2
LOCAL progress_vbox, test_execute, test_close, test_clear, test_vbox, test_hbox, test_label1, test_label2, lm, lang, test_view2
LOCAL test_scrolled1, test_scrolled2, cnewtab_menu, copentab_menu, cclosetab_menu, file_filter1, file_filter2, scrolled, help_menu
LOCAL vbox, accel_group, find_ok, find_get, find_repl, find_vbox, find_hbox1, find_hbox2, find_hbox3, find_label1, find_label2
LOCAL sub_menu, menu_0, menu_1, menu_2, menu_3, menu_4, menu_5, compiling_image, compiling_label, compiling_hbox
LOCAL print_ok, print_cancel, print_vbox, print_vbox1, print_vbox2, print_hbox, print_hbox2
LOCAL file$, info$
' Initialize GTK
gtk_init(0, 0)
' Check version
IF LEN(gtk_check_version$(3, 0, 0)) > 0 THEN
PRINT "Warning! BaCon needs GTK 3.0.0 or higher to run properly: ", gtk_check_version$(3, 0, 0)
PRINT "Some functions may not be available."
END IF
' Define main window
g_Win = gtk_window_new(GTK_WINDOW_TOPLEVEL)
gtk_window_set_title(g_Win, DEFTITLE$)
gtk_window_set_position(g_Win, 1)
gtk_window_set_default_size(g_Win, 700, 500)
gtk_window_set_icon_name(g_Win, "gtk-edit")
' Define callback when deleting window
g_signal_connect_data(g_Win, "delete-event", Exit_Prog, 0, 0, 0)
' Create filefilters
file_filter1 = gtk_file_filter_new()
gtk_file_filter_set_name(file_filter1, "BaCon source files (*.bac)")
gtk_file_filter_add_pattern(file_filter1, "*.bac")
file_filter2 = gtk_file_filter_new()
gtk_file_filter_set_name(file_filter2, "All files (*)")
gtk_file_filter_add_pattern(file_filter2, "*")
' Create FILE OPEN
g_File_dialog = gtk_file_chooser_dialog_new("Open file...", g_Win, 0, "gtk-cancel", GTK_RESPONSE_CANCEL, "gtk-open", GTK_RESPONSE_ACCEPT, NULL)
gtk_window_set_transient_for(g_File_dialog, g_Win)
gtk_window_set_position(g_File_dialog, GTK_WIN_POS_CENTER_ON_PARENT)
gtk_window_set_default_size(g_File_dialog, 300, 300)
gtk_window_set_icon_name(g_File_dialog, "gtk-open")
g_signal_connect_data(g_File_dialog, "delete-event", gtk_widget_hide_on_delete, 0, 0, 0)
g_signal_connect_data(g_File_dialog, "response", Handle_Open_Dialog, 0, 0, 0)
gtk_file_chooser_add_filter(g_File_dialog, file_filter1)
gtk_file_chooser_add_filter(g_File_dialog, file_filter2)
' Create URL open
g_Url_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL)
gtk_window_set_title(g_Url_dialog, "Load BaCon file over HTTP...")
gtk_window_set_transient_for(g_Url_dialog, g_Win)
gtk_window_set_position(g_Url_dialog, GTK_WIN_POS_CENTER_ON_PARENT)
gtk_window_set_default_size(g_Url_dialog, 400, -1)
gtk_window_set_icon_name(g_Url_dialog, "gtk-network")
url_label = gtk_label_new("URL:")
gtk_widget_set_size_request(url_label, 60, -1)
gtk_misc_set_alignment(url_label, 1.0, 0.5)
g_Url_entry = gtk_entry_new()
gtk_entry_set_text(g_Url_entry, "http://www.basic-converter.org/")
sep14 = gtk_hseparator_new()
url_cancel = gtk_button_new_from_stock("gtk-cancel")
url_load = gtk_button_new_from_stock("gtk-open")
url_vbox = gtk_vbox_new(0, 0)
url_hbox1 = gtk_hbox_new(0, 0)
url_hbox2 = gtk_hbox_new(0, 0)
gtk_box_pack_start(url_hbox1, url_label, 0, 0, 1)
gtk_box_pack_end(url_hbox1, g_Url_entry, 1, 1, 1)
gtk_box_pack_start(url_hbox2, url_cancel, 0, 0, 1)
gtk_box_pack_end(url_hbox2, url_load, 0, 0, 1)
gtk_box_pack_start(url_vbox, url_hbox1, 0, 0, 1)
gtk_box_pack_start(url_vbox, sep14, 0, 0, 1)
gtk_box_pack_start(url_vbox, url_hbox2, 0, 0, 1)
gtk_container_add(g_Url_dialog, url_vbox)
g_signal_connect_data(url_cancel, "clicked", Hide_Dialog, g_Url_dialog, 0, 0)
g_signal_connect_data(url_load, "clicked", Handle_Open_Url, 0, 0, 0)
g_signal_connect_data(g_Url_entry, "activate", Handle_Open_Url, 0, 0, 0)
g_signal_connect_data(g_Url_dialog, "delete-event", gtk_widget_hide_on_delete, 0, 0, 0)
' Create SAVE AS
g_Save_dialog = gtk_file_chooser_dialog_new("Save file as...", g_Win, 1, "gtk-cancel", GTK_RESPONSE_CANCEL, "gtk-save", GTK_RESPONSE_ACCEPT, NULL)
gtk_window_set_transient_for(g_Save_dialog, g_Win)
gtk_window_set_position(g_Save_dialog, GTK_WIN_POS_CENTER_ON_PARENT)
gtk_window_set_default_size(g_Save_dialog, 300, 300)
gtk_window_set_icon_name(g_Save_dialog, "gtk-save-as")
g_signal_connect_data(g_Save_dialog, "delete-event", gtk_widget_hide_on_delete, 0, 0, 0)
g_signal_connect_data(g_Save_dialog, "response", Handle_Save_Dialog, 0, 0, 0)
gtk_file_chooser_add_filter(g_Save_dialog, file_filter1)
gtk_file_chooser_add_filter(g_Save_dialog, file_filter2)
' Create FONT SELECTION
g_Font_dialog = gtk_font_selection_dialog_new("Select font...")
gtk_window_set_transient_for(g_Font_dialog, g_Win)
gtk_window_set_position(g_Font_dialog, GTK_WIN_POS_CENTER_ON_PARENT)
gtk_window_set_default_size(g_Font_dialog, 300, 300)
gtk_window_set_icon_name(g_Font_dialog, "gtk-preferences")
g_signal_connect_data(g_Font_dialog, "delete-event", gtk_widget_hide_on_delete, 0, 0, 0)
g_signal_connect_data(g_Font_dialog, "response", Handle_Font_Dialog, 0, 0, 0)
' Create COLOR SELECTION
g_Color_dialog = gtk_color_selection_dialog_new("Select color...")
gtk_window_set_transient_for(g_Color_dialog, g_Win)
gtk_window_set_position(g_Color_dialog, GTK_WIN_POS_CENTER_ON_PARENT)
gtk_window_set_default_size(g_Color_dialog, 300, 300)
gtk_window_set_icon_name(g_Color_dialog, "gtk-color-picker")
g_signal_connect_data(g_Color_dialog, "delete-event", gtk_widget_hide_on_delete, 0, 0, 0)
g_signal_connect_data(g_Color_dialog, "response", Handle_Color_Dialog, 0, 0, 0)
' Create PRINT dialog
g_Print_dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL)
gtk_window_set_title(g_Print_dialog, "Print BaCon program")
gtk_window_set_transient_for(g_Print_dialog, g_Win)
gtk_window_set_position(g_Print_dialog, GTK_WIN_POS_CENTER_ON_PARENT)
gtk_window_set_icon_name(g_Print_dialog, "gtk-print")
g_Print_combo = gtk_combo_box_text_new()
IF ISFALSE(LEN(EXEC$(CONCAT$("which lpstat 2>/dev/null")))) THEN
gtk_combo_box_text_append_text(g_Print_combo, "No printing system found")
ELSE
info$ = EXEC$("lpstat -a 2>/dev/null")
SPLIT info$ BY NL$ TO printer$ SIZE bacamount
IF bacamount > 0 THEN
FOR x = 1 TO bacamount
SPLIT printer$[x] BY " " TO item$ SIZE size
gtk_combo_box_text_append_text(g_Print_combo, item$[1])
NEXT
ELSE
gtk_combo_box_text_append_text(g_Print_combo, "")
END IF
END IF
gtk_combo_box_set_active(g_Print_combo, 0)
g_Print_check1 = gtk_radio_button_new_with_label_from_widget(0, "Portrait")
g_Print_check2 = gtk_radio_button_new_with_label_from_widget(g_Print_check1, "Landscape")
g_Print_check3 = gtk_radio_button_new_with_label_from_widget(0, "One sided")
g_Print_check4 = gtk_radio_button_new_with_label_from_widget(g_Print_check3, "Two sided")
print_ok = gtk_button_new_from_stock("gtk-print")
print_cancel = gtk_button_new_from_stock("gtk-cancel")
sep16 = gtk_hseparator_new()
print_vbox = gtk_vbox_new(0, 0)
print_vbox1 = gtk_vbox_new(0, 0)
print_vbox2 = gtk_vbox_new(0, 0)
gtk_box_pack_start(print_vbox1, g_Print_check1, 0, 0, 1)
gtk_box_pack_start(print_vbox1, g_Print_check2, 0, 0, 1)
gtk_box_pack_start(print_vbox2, g_Print_check3, 0, 0, 1)
gtk_box_pack_start(print_vbox2, g_Print_check4, 0, 0, 1)
gtk_container_set_border_width(print_vbox1, 5)
gtk_container_set_border_width(print_vbox2, 5)
print_hbox2 = gtk_hbox_new(0, 0)
gtk_box_pack_start(print_hbox2, print_vbox1, 0, 0, 1)
gtk_box_pack_end(print_hbox2, print_vbox2, 0, 0, 1)
print_hbox1 = gtk_hbox_new(0, 0)
gtk_box_pack_start(print_vbox, g_Print_combo, 0, 0, 1)
gtk_box_pack_start(print_vbox, print_hbox2, 0, 0, 1)
gtk_box_pack_end(print_hbox1, print_ok, 0, 0, 1)
gtk_box_pack_start(print_hbox1, print_cancel, 0, 0, 1)
gtk_box_pack_start(print_vbox, sep16, 0, 0, 1)
gtk_box_pack_start(print_vbox, print_hbox1, 0, 0, 1)
gtk_container_add(g_Print_dialog, print_vbox)
g_signal_connect_data(print_cancel, "clicked", Hide_Dialog, g_Print_dialog, 0, 0)
g_signal_connect_data(print_ok, "clicked", Handle_Print_Dialog, 0, 0, 0)
g_signal_connect_data(g_Print_dialog, "delete-event", gtk_widget_hide_on_delete, 0, 0, 0)
' Define the global clipboard
g_ClipBoard = gtk_clipboard_get(gdk_atom_intern("CLIPBOARD", 0))
' Create menubar
menubar = gtk_menu_bar_new()
' Create FILE submenu
fmenu = gtk_menu_new()
ftear = gtk_tearoff_menu_item_new()
file_menu = gtk_menu_item_new_with_mnemonic("_Open...")
url_menu = gtk_menu_item_new_with_mnemonic("Open _URL...")
save_menu = gtk_menu_item_new_with_mnemonic("_Save")
saveas_menu = gtk_menu_item_new_with_mnemonic("S_ave as...")
sep1 = gtk_menu_item_new()
print_menu = gtk_menu_item_new_with_mnemonic("_Print...")
sep15 = gtk_menu_item_new()
newtab_menu = gtk_menu_item_new_with_mnemonic("_New tab")
opentab_menu = gtk_menu_item_new_with_mnemonic("O_pen tab...")
closetab_menu = gtk_menu_item_new_with_mnemonic("_Close tab")
sep5 = gtk_menu_item_new()
exit_menu = gtk_menu_item_new_with_mnemonic("_Exit")
gtk_menu_shell_append(fmenu, ftear)
gtk_menu_shell_append(fmenu, file_menu)
gtk_menu_shell_append(fmenu, url_menu)
gtk_menu_shell_append(fmenu, save_menu)
gtk_menu_shell_append(fmenu, saveas_menu)
gtk_menu_shell_append(fmenu, sep1)
gtk_menu_shell_append(fmenu, print_menu)
gtk_menu_shell_append(fmenu, sep15)
gtk_menu_shell_append(fmenu, newtab_menu)
gtk_menu_shell_append(fmenu, opentab_menu)
gtk_menu_shell_append(fmenu, closetab_menu)
gtk_menu_shell_append(fmenu, sep5)
gtk_menu_shell_append(fmenu, exit_menu)
fmenu_item = gtk_menu_item_new_with_mnemonic("_File")
gtk_menu_item_set_submenu(fmenu_item, fmenu)
gtk_menu_shell_append(menubar, fmenu_item)
' Create EDIT submenu
emenu = gtk_menu_new()
etear = gtk_tearoff_menu_item_new()
cut_menu = gtk_menu_item_new_with_mnemonic("_Cut")
copy_menu = gtk_menu_item_new_with_mnemonic("C_opy")
paste_menu = gtk_menu_item_new_with_mnemonic("_Paste")
sep4 = gtk_menu_item_new()
undo_menu = gtk_menu_item_new_with_mnemonic("_Undo")
redo_menu = gtk_menu_item_new_with_mnemonic("_Redo")
sep6 = gtk_menu_item_new()
select_menu = gtk_menu_item_new_with_mnemonic("_Select all")
sep7 = gtk_menu_item_new()
find_menu = gtk_menu_item_new_with_mnemonic("_Find...")
gtk_menu_shell_append(emenu, etear)
gtk_menu_shell_append(emenu, cut_menu)
gtk_menu_shell_append(emenu, copy_menu)
gtk_menu_shell_append(emenu, paste_menu)
gtk_menu_shell_append(emenu, sep4)
gtk_menu_shell_append(emenu, undo_menu)
gtk_menu_shell_append(emenu, redo_menu)
gtk_menu_shell_append(emenu, sep6)
gtk_menu_shell_append(emenu, select_menu)
gtk_menu_shell_append(emenu, sep7)
gtk_menu_shell_append(emenu, find_menu)
emenu_item = gtk_menu_item_new_with_mnemonic("_Edit")
gtk_menu_item_set_submenu(emenu_item, emenu)
gtk_menu_shell_append(menubar, emenu_item)
' Create OPTIONS submenu
omenu = gtk_menu_new()
otear = gtk_tearoff_menu_item_new()
indent_menu = gtk_check_menu_item_new_with_mnemonic("_Auto indent")
linenr_menu = gtk_check_menu_item_new_with_mnemonic("_Line numbers")
wrap_menu = gtk_check_menu_item_new_with_mnemonic("_Wrap lines")
page_menu = gtk_check_menu_item_new_with_mnemonic("_Restore tabs")
sep2 = gtk_menu_item_new()
font_menu = gtk_menu_item_new_with_mnemonic("_Select font...")
color_menu = gtk_menu_item_new_with_mnemonic("_Background color...")
spacing_menu = gtk_menu_item_new_with_mnemonic("L_ine spacing")
sep3 = gtk_menu_item_new()
syntax_menu = gtk_menu_item_new_with_mnemonic("_Update syntaxfile...")
gtk_menu_shell_append(omenu, otear)
gtk_menu_shell_append(omenu, indent_menu)
gtk_menu_shell_append(omenu, linenr_menu)
gtk_menu_shell_append(omenu, wrap_menu)
gtk_menu_shell_append(omenu, page_menu)
gtk_menu_shell_append(omenu, sep2)
gtk_menu_shell_append(omenu, font_menu)
gtk_menu_shell_append(omenu, color_menu)
gtk_menu_shell_append(omenu, spacing_menu)
gtk_menu_shell_append(omenu, sep3)
gtk_menu_shell_append(omenu, syntax_menu)
omenu_item = gtk_menu_item_new_with_mnemonic("_Options")
gtk_menu_item_set_submenu(omenu_item, omenu)
sub_menu = gtk_menu_new()
menu_0 = gtk_menu_item_new_with_label("0 pixels")
menu_1 = gtk_menu_item_new_with_label("1 pixel")
menu_2 = gtk_menu_item_new_with_label("2 pixels")
menu_3 = gtk_menu_item_new_with_label("3 pixels")
menu_4 = gtk_menu_item_new_with_label("4 pixels")
menu_5 = gtk_menu_item_new_with_label("5 pixels")
gtk_menu_shell_append(sub_menu, menu_0)
gtk_menu_shell_append(sub_menu, menu_1)
gtk_menu_shell_append(sub_menu, menu_2)
gtk_menu_shell_append(sub_menu, menu_3)
gtk_menu_shell_append(sub_menu, menu_4)
gtk_menu_shell_append(sub_menu, menu_5)
gtk_menu_item_set_submenu(spacing_menu, sub_menu)
gtk_menu_shell_append(menubar, omenu_item)
' Create CONVERT menu
comenu = gtk_menu_new()
cotear = gtk_tearoff_menu_item_new()
conv_menu = gtk_menu_item_new_with_mnemonic("_Convert...")
exec_menu = gtk_menu_item_new_with_mnemonic("_Execute...")
sep12 = gtk_menu_item_new()
test_menu = gtk_menu_item_new_with_mnemonic("_BaCon shell...")
gtk_menu_shell_append(comenu, cotear)
gtk_menu_shell_append(comenu, conv_menu)
gtk_menu_shell_append(comenu, exec_menu)
gtk_menu_shell_append(comenu, sep12)
gtk_menu_shell_append(comenu, test_menu)
comenu_item = gtk_menu_item_new_with_mnemonic("_Tools")
gtk_menu_item_set_submenu(comenu_item, comenu)
gtk_menu_shell_append(menubar, comenu_item)
' Create HELP submenu
hmenu = gtk_menu_new()
htear = gtk_tearoff_menu_item_new()
help_menu = gtk_menu_item_new_with_mnemonic("_Documentation")
about_menu = gtk_menu_item_new_with_mnemonic("_About...")
gtk_menu_shell_append(hmenu, htear)
gtk_menu_shell_append(hmenu, help_menu)
gtk_menu_shell_append(hmenu, about_menu)
hmenu_item = gtk_menu_item_new_with_mnemonic("_Help")
gtk_menu_item_set_submenu(hmenu_item, hmenu)
gtk_menu_shell_append(menubar, hmenu_item)
' Create FIND dialog
g_Find = gtk_window_new(GTK_WINDOW_TOPLEVEL)
gtk_window_set_title(g_Find, "Find and replace")
gtk_window_set_transient_for(g_Find, g_Win)
gtk_window_set_position(g_Find, GTK_WIN_POS_CENTER_ON_PARENT)
gtk_window_set_default_size(g_Find, 350, -1)
gtk_window_set_icon_name(g_Find, "gtk-find")
find_label1 = gtk_label_new("Find:")
g_Find_entry = gtk_entry_new()
gtk_widget_set_size_request(find_label1, 80, -1)
gtk_misc_set_alignment(find_label1, 1.0, 0.5)
find_label2 = gtk_label_new("Replace:")
g_Repl_entry = gtk_entry_new()
gtk_widget_set_size_request(find_label2, 80, -1)
gtk_misc_set_alignment(find_label2, 1.0, 0.5)
sep11 = gtk_hseparator_new()
find_ok = gtk_button_new_from_stock("gtk-close")
find_get = gtk_button_new_from_stock("gtk-find")
find_repl = gtk_button_new_from_stock("gtk-find-and-replace")
find_vbox = gtk_vbox_new(0, 0)
find_hbox1 = gtk_hbox_new(0, 0)
find_hbox2 = gtk_hbox_new(0, 0)
find_hbox3 = gtk_hbox_new(0, 0)
gtk_box_pack_start(find_hbox2, find_label1, 0, 0, 1)
gtk_box_pack_end(find_hbox2, g_Find_entry, 1, 1, 1)
gtk_box_pack_start(find_hbox3, find_label2, 0, 0, 1)
gtk_box_pack_end(find_hbox3, g_Repl_entry, 1, 1, 1)
gtk_box_pack_start(find_vbox, find_hbox2, 0, 0, 1)
gtk_box_pack_start(find_vbox, find_hbox3, 0, 0, 1)
gtk_box_pack_start(find_vbox, sep11, 0, 0, 1)
gtk_box_pack_end(find_hbox1, find_get, 0, 0, 1)
gtk_box_pack_end(find_hbox1, find_repl, 0, 0, 1)
gtk_box_pack_end(find_hbox1, find_ok, 0, 0, 1)
gtk_box_pack_start(find_vbox, find_hbox1, 0, 0, 1)
gtk_container_add(g_Find, find_vbox)
g_signal_connect_data(find_ok, "clicked", Hide_Dialog, g_Find, 0, 0)
g_signal_connect_data(find_get, "clicked", Find_Term, 0, 0, 0)
g_signal_connect_data(g_Find_entry, "activate", Find_Term, 0, 0, 0)
g_signal_connect_data(find_repl, "clicked", Find_Term, 1, 0, 0)
g_signal_connect_data(g_Find, "delete-event", gtk_widget_hide_on_delete, 0, 0, 0)
' Create progress dialog for conversion
g_Progress = gtk_window_new(GTK_WINDOW_TOPLEVEL)
gtk_window_set_transient_for(g_Progress, g_Win)
gtk_window_set_position(g_Progress, GTK_WIN_POS_CENTER_ON_PARENT)
gtk_widget_set_size_request(g_Progress, 350, -1)
gtk_window_set_resizable(g_Progress, 0)
gtk_window_set_icon_name(g_Progress, "gtk-convert")
g_Progressbar = gtk_progress_bar_new()
gtk_container_add(g_Progress, g_Progressbar)
g_signal_connect_data(g_Progress, "delete-event", gtk_widget_hide_on_delete, 0, 0, 0)
g_object_set(g_Progressbar, "show-text", TRUE, NULL)
' Create OPTIONS dialog
g_Options = gtk_window_new(GTK_WINDOW_TOPLEVEL)
gtk_window_set_title(g_Options, "Conversion options")
gtk_window_set_transient_for(g_Options, g_Win)
gtk_window_set_position(g_Options, GTK_WIN_POS_CENTER_ON_PARENT)
gtk_window_set_resizable(g_Options, 0)
gtk_window_set_icon_name(g_Options, "gtk-preferences")
compiler_label = gtk_label_new("C compiler:")
gtk_misc_set_alignment(compiler_label, 1.0, 0.5)
g_Compiler_entry = gtk_entry_new()
gtk_entry_set_text(g_Compiler_entry, "cc")
flags_label = gtk_label_new("Libraries:")
gtk_misc_set_alignment(flags_label, 1.0, 0.5)
g_Flags_entry = gtk_entry_new()
options_label = gtk_label_new("Options:")
gtk_misc_set_alignment(options_label, 1.0, 0.5)
g_Options_entry = gtk_entry_new()
inc_label = gtk_label_new("Include files:")
gtk_misc_set_alignment(inc_label, 1.0, 0.5)
g_Inc_entry = gtk_entry_new()
tmpdir_label = gtk_label_new("Temporary dir:")
gtk_misc_set_alignment(tmpdir_label, 1.0, 0.5)
g_Tmpdir_entry = gtk_entry_new()
gtk_entry_set_text(g_Tmpdir_entry, "/tmp")
sep8 = gtk_hseparator_new()
g_So_check = gtk_check_button_new_with_label("Create Shared Object")
g_Con_check = gtk_check_button_new_with_label("Do not compile, only convert")
g_Cpp_check = gtk_check_button_new_with_label("Invoke C Preprocessor")
g_Pre_check = gtk_check_button_new_with_label("Preserve temporary files")
g_Gettext_check = gtk_check_button_new_with_label("Extract gettext strings")
sep9 = gtk_hseparator_new()
options_close = gtk_button_new_from_stock("gtk-convert")
options_cancel = gtk_button_new_from_stock("gtk-cancel")
options_vbox = gtk_vbox_new(0, 0)
options_hbox1 = gtk_hbox_new(0, 0)
gtk_box_pack_start(options_hbox1, compiler_label, 1, 1, 1)
gtk_box_pack_end(options_hbox1, g_Compiler_entry, 0, 0, 1)
options_hbox2 = gtk_hbox_new(0, 0)
gtk_box_pack_start(options_hbox2, flags_label, 1, 1, 1)
gtk_box_pack_end(options_hbox2, g_Flags_entry, 0, 0, 1)
options_hbox3 = gtk_hbox_new(0, 0)
gtk_box_pack_start(options_hbox3, options_label, 1, 1, 1)
gtk_box_pack_end(options_hbox3, g_Options_entry, 0, 0, 1)
options_hbox4 = gtk_hbox_new(0, 0)
gtk_box_pack_start(options_hbox4, inc_label, 1, 1, 1)
gtk_box_pack_end(options_hbox4, g_Inc_entry, 0, 0, 1)
options_hbox5 = gtk_hbox_new(0, 0)
gtk_box_pack_start(options_hbox5, tmpdir_label, 1, 1, 1)
gtk_box_pack_end(options_hbox5, g_Tmpdir_entry, 0, 0, 1)
options_hbox6 = gtk_hbox_new(0, 0)
gtk_box_pack_start(options_hbox6, options_cancel, 0, 0, 1)
gtk_box_pack_end(options_hbox6, options_close, 0, 0, 1)
gtk_box_pack_start(options_vbox, options_hbox1, 0, 0, 1)
gtk_box_pack_start(options_vbox, options_hbox2, 0, 0, 1)
gtk_box_pack_start(options_vbox, options_hbox3, 0, 0, 1)
gtk_box_pack_start(options_vbox, options_hbox4, 0, 0, 1)
gtk_box_pack_start(options_vbox, options_hbox5, 0, 0, 1)
gtk_box_pack_start(options_vbox, sep8, 0, 0, 1)
gtk_box_pack_start(options_vbox, g_So_check, 0, 0, 1)
gtk_box_pack_start(options_vbox, g_Con_check, 0, 0, 1)
gtk_box_pack_start(options_vbox, g_Cpp_check, 0, 0, 1)
gtk_box_pack_start(options_vbox, g_Pre_check, 0, 0, 1)
gtk_box_pack_start(options_vbox, g_Gettext_check, 0, 0, 1)
gtk_box_pack_start(options_vbox, sep9, 0, 0, 1)
gtk_box_pack_start(options_vbox, options_hbox6, 0, 0, 1)
gtk_container_add(g_Options, options_vbox)
g_signal_connect_data(options_cancel, "clicked", Hide_Dialog, g_Options, 0, 0)
g_signal_connect_data(options_close, "clicked", Convert_Source, g_Options, 0, 0)
g_signal_connect_data(g_Options, "delete-event", gtk_widget_hide_on_delete, 0, 0, 0)
gtk_widget_grab_focus(options_close)
' Create "Compiling now..." dialog
g_Compiling = gtk_window_new(GTK_WINDOW_TOPLEVEL)
gtk_window_set_title(g_Compiling, "Informational")
gtk_window_set_transient_for(g_Compiling, g_Win)
gtk_window_set_position(g_Compiling, GTK_WIN_POS_CENTER_ON_PARENT)
gtk_window_set_resizable(g_Compiling, 0)
gtk_window_set_icon_name(g_Compiling, "gtk-preferences")
compiling_image = gtk_image_new_from_stock("gtk-dialog-info", GTK_ICON_SIZE_DIALOG)
compiling_label = gtk_label_new("Compiling, please wait...")
compiling_hbox = gtk_hbox_new(0, 10)
gtk_box_pack_start(compiling_hbox, compiling_image, 0, 0, 5)
gtk_box_pack_start(compiling_hbox, compiling_label, 0, 0, 5)
gtk_container_add(g_Compiling, compiling_hbox)
' Create EXECUTE dialog
g_Execute = gtk_window_new(GTK_WINDOW_TOPLEVEL)
gtk_window_set_title(g_Execute, "Execute options")
gtk_window_set_transient_for(g_Execute, g_Win)
gtk_window_set_position(g_Execute, GTK_WIN_POS_CENTER_ON_PARENT)
gtk_window_set_default_size(g_Execute, 540, -1)
gtk_window_set_icon_name(g_Execute, "gtk-preferences")
gui_radio = gtk_radio_button_new_with_label_from_widget(0, "GUI application")
con_radio = gtk_radio_button_new_with_label_from_widget(gui_radio, "Console application")
g_Shell_label1 = gtk_label_new("Default shell:")
gtk_widget_set_size_request(g_Shell_label1, 120, -1)
gtk_misc_set_alignment(g_Shell_label1, 1.0, 0.5)
g_Shell_entry1 = gtk_entry_new()
gtk_entry_set_text(g_Shell_entry1, "xterm -hold -sb -geometry 132x40 -e @")
g_Shell_label2 = gtk_label_new("Arguments:")
gtk_widget_set_size_request(g_Shell_label2, 120, -1)
gtk_misc_set_alignment(g_Shell_label2, 1.0, 0.5)
g_Shell_entry2 = gtk_entry_new()
CALL Disable_Console
sep10 = gtk_hseparator_new()
exec_close = gtk_button_new_from_stock("gtk-execute")
exec_cancel = gtk_button_new_from_stock("gtk-cancel")
execute_vbox = gtk_vbox_new(0, 0)
execute_hbox1 = gtk_hbox_new(0, 0)
gtk_box_pack_start(execute_hbox1, g_Shell_label1, 0, 0, 1)
gtk_box_pack_end(execute_hbox1, g_Shell_entry1, 1, 1, 1)
execute_hbox3 = gtk_hbox_new(0, 0)
gtk_box_pack_start(execute_hbox3, g_Shell_label2, 0, 0, 1)
gtk_box_pack_end(execute_hbox3, g_Shell_entry2, 1, 1, 1)
execute_hbox2 = gtk_hbox_new(0, 0)
gtk_box_pack_start(execute_hbox2, exec_cancel, 0, 0, 1)
gtk_box_pack_end(execute_hbox2, exec_close, 0, 0, 1)
gtk_box_pack_start(execute_vbox, gui_radio, 0, 0, 1)
gtk_box_pack_start(execute_vbox, con_radio, 0, 0, 1)
gtk_box_pack_start(execute_vbox, execute_hbox1, 0, 0, 1)
gtk_box_pack_start(execute_vbox, execute_hbox3, 0, 0, 1)
gtk_box_pack_start(execute_vbox, sep10, 0, 0, 1)
gtk_box_pack_start(execute_vbox, execute_hbox2, 0, 0, 1)
gtk_container_add(g_Execute, execute_vbox)
g_signal_connect_data(gui_radio, "clicked", Disable_Console, 0, 0, 0)
g_signal_connect_data(con_radio, "clicked", Enable_Console, 0, 0, 0)
g_signal_connect_data(exec_cancel, "clicked", Hide_Dialog, g_Execute, 0, 0)
g_signal_connect_data(exec_close, "clicked", Execute_Binary, g_Execute, 0, 0)
g_signal_connect_data(g_Shell_entry1, "activate", Execute_Binary, g_Execute, 0, 0)
g_signal_connect_data(g_Shell_entry2, "activate", Execute_Binary, g_Execute, 0, 0)
g_signal_connect_data(g_Execute, "delete-event", gtk_widget_hide_on_delete, 0, 0, 0)
gtk_toggle_button_set_active(con_radio, 1)
gtk_widget_grab_focus(exec_close)
' Create TEST dialog
g_Test = gtk_window_new(GTK_WINDOW_TOPLEVEL)
gtk_window_set_title(g_Test, "BaCon Shell")
gtk_window_set_transient_for(g_Test, g_Win)
gtk_window_set_position(g_Test, GTK_WIN_POS_CENTER_ON_PARENT)
gtk_window_set_default_size(g_Test, 450, -1)
gtk_window_set_icon_name(g_Test, "gtk-preferences")
test_label1 = gtk_frame_new(" Input test code ")
lm = gtk_source_language_manager_get_default()
lang = gtk_source_language_manager_get_language(lm, "bacon")
g_Test_buffer1 = gtk_source_buffer_new_with_language(lang)
gtk_source_buffer_set_highlight_matching_brackets(g_Test_buffer1, 1)
g_Test_view1 = gtk_source_view_new_with_buffer(g_Test_buffer1)
test_scrolled1 = gtk_scrolled_window_new(0, 0)
gtk_scrolled_window_set_policy(test_scrolled1, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC)
gtk_scrolled_window_set_shadow_type(test_scrolled1, GTK_SHADOW_ETCHED_IN)
gtk_container_add(test_scrolled1, g_Test_view1)
gtk_text_view_set_editable(g_Test_view1, TRUE)
gtk_text_view_set_wrap_mode(g_Test_view1, GTK_WRAP_WORD)
gtk_widget_set_size_request(test_scrolled1, -1, 100)
gtk_container_set_border_width(test_scrolled1, 5)
gtk_container_add(test_label1, test_scrolled1)
test_label2 = gtk_frame_new(" Result ")
g_Test_buffer2 = gtk_text_buffer_new(0)
test_view2 = gtk_text_view_new_with_buffer(g_Test_buffer2)
test_scrolled2 = gtk_scrolled_window_new(0, 0)
gtk_scrolled_window_set_policy(test_scrolled2, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC)
gtk_scrolled_window_set_shadow_type(test_scrolled2, GTK_SHADOW_ETCHED_IN)
gtk_container_add(test_scrolled2, test_view2)
gtk_text_view_set_editable(test_view2, FALSE)
gtk_text_view_set_wrap_mode(test_view2, GTK_WRAP_NONE)
gtk_widget_set_size_request(test_scrolled2, -1, 150)
gtk_container_set_border_width(test_scrolled2, 5)
gtk_container_add(test_label2, test_scrolled2)
sep13 = gtk_hseparator_new()
test_execute = gtk_button_new_from_stock("gtk-execute")
test_close = gtk_button_new_from_stock("gtk-close")
test_clear = gtk_button_new_from_stock("gtk-clear")
test_vbox = gtk_vbox_new(0, 0)
test_hbox = gtk_hbox_new(0, 0)
gtk_box_pack_start(test_hbox, test_close, 0, 0, 1)
gtk_box_pack_end(test_hbox, test_execute, 0, 0, 1)
gtk_box_pack_end(test_hbox, test_clear, 0, 0, 1)
gtk_box_pack_start(test_vbox, test_label1, 1, 1, 1)
gtk_box_pack_start(test_vbox, test_label2, 1, 1, 1)
gtk_box_pack_start(test_vbox, sep13, 0, 0, 1)
gtk_box_pack_start(test_vbox, test_hbox, 0, 0, 1)
gtk_container_add(g_Test, test_vbox)
g_signal_connect_data(test_execute, "clicked", Execute_Line, 0, 0, 0)
g_signal_connect_data(test_clear, "clicked", Clear_Test_Area, 0, 0, 0)
g_signal_connect_data(test_close, "clicked", Hide_Dialog, g_Test, 0, 0)
g_signal_connect_data(g_Test, "delete-event", gtk_widget_hide_on_delete, 0, 0, 0)
' Create dialog for HTML help
g_Html = gtk_window_new(GTK_WINDOW_TOPLEVEL)
gtk_window_set_title(g_Html, "HTML Help")
gtk_window_set_position(g_Html, GTK_WIN_POS_MOUSE)
gtk_window_set_default_size(g_Html, 1000, 600)
gtk_window_set_icon_name(g_Html, "gtk-help")
IF g_LIBGTKWEBKIT OR g_LIBGTKHTML THEN
IF g_LIBGTKWEBKIT THEN
g_Html_widget = webkit_web_view_new()
webkit_settings = webkit_web_settings_new()
g_object_set(webkit_settings, "enable-scripts", FALSE, "enable-dns-prefetching", FALSE, NULL)
webkit_web_view_set_settings(g_Html_widget, webkit_settings)
ELSE
g_Html_widget = gtk_html_new()
END IF
scrolled = gtk_scrolled_window_new(0, 0)
gtk_scrolled_window_set_policy(scrolled, 1, 1)
gtk_scrolled_window_set_shadow_type(scrolled, 3)
gtk_container_add(scrolled, g_Html_widget)
gtk_container_add(g_Html, scrolled)
END IF
g_signal_connect_data(g_Html, "delete-event", gtk_widget_hide_on_delete, 0, 0, 0)
' Create contextmenu
g_Cmenu = gtk_menu_new()
cnewtab_menu = gtk_menu_item_new_with_mnemonic("New tab")
copentab_menu = gtk_menu_item_new_with_mnemonic("Open tab...")
cclosetab_menu = gtk_menu_item_new_with_mnemonic("Close tab")
gtk_menu_shell_append(g_Cmenu, cnewtab_menu)
gtk_menu_shell_append(g_Cmenu, copentab_menu)
gtk_menu_shell_append(g_Cmenu, cclosetab_menu)
g_signal_connect_data(cnewtab_menu, "activate", Create_Page, 0, 0, 0)
g_signal_connect_data(copentab_menu, "activate", Open_Page, 0, 0, 0)
g_signal_connect_data(cclosetab_menu, "activate", Close_Tab, 0, 0, 0)
gtk_widget_show_all(g_Cmenu)
' Create notebook
g_Notebook = gtk_notebook_new()
g_signal_connect_data(g_Notebook, "button-press-event", Show_Popup, 0, 0, 0)
g_signal_connect_data(g_Notebook, "page-reordered", Reorder_Tabs, 0, 0, 0)
gtk_notebook_set_scrollable(g_Notebook, TRUE)
' Create statusbar
g_Statusbar = gtk_statusbar_new()
g_Msgcid = gtk_statusbar_get_context_id(g_Statusbar, "bacon")
gtk_statusbar_push(g_Statusbar, g_Msgcid, CONCAT$("Compiled with BaCon ", VERSION$))
' Get filenames from arguments
SPLIT CHOP$(ARGUMENT$) BY " " TO bacfiles$ SIZE bacamount
IF bacamount > 1 THEN
FOR x = 2 TO bacamount
IF LEFT$(bacfiles$[x], 7) = "http://" THEN
file$ = Download_File$(bacfiles$[x], FALSE)
IF LEN(file$) > 0 THEN
Create_Page
Load_File(file$, FALSE)
END IF
ELSE
IF NOT(FILEEXISTS(bacfiles$[x])) THEN
CALL Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("Cannot find file '", bacfiles$[x], "'!"), -1)
ELSE
Create_Page
Load_File(bacfiles$[x], TRUE)
END IF
END IF
NEXT
ELSE
' See if files are saved
Load_Files_Into_GUI
END IF
' Nothing loaded? Then simply create new page
IF gtk_notebook_get_n_pages(g_Notebook) IS 0 THEN Create_Page
' Setup vbox
vbox = gtk_vbox_new(0, 0)
gtk_box_pack_start(vbox, menubar, 0, 0, 0)
gtk_box_pack_start(vbox, g_Notebook, 1, 1, 2)
gtk_box_pack_start(vbox, g_Statusbar, 0, 0, 1)
' Finalize GUI
gtk_container_add(g_Win, vbox)
gtk_widget_show_all(g_Win)
' Define some accelerator keys
accel_group = gtk_accel_group_new()
gtk_window_add_accel_group(g_Win, accel_group)
gtk_widget_add_accelerator(file_menu, "activate", accel_group, gdk_keyval_from_name("o"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(url_menu, "activate", accel_group, gdk_keyval_from_name("u"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(save_menu, "activate", accel_group, gdk_keyval_from_name("s"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(saveas_menu, "activate", accel_group, gdk_keyval_from_name("s"), GDK_CONTROL_MASK|GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(newtab_menu, "activate", accel_group, gdk_keyval_from_name("n"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(opentab_menu, "activate", accel_group, gdk_keyval_from_name("n"), GDK_CONTROL_MASK|GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(closetab_menu, "activate", accel_group, gdk_keyval_from_name("t"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(exit_menu, "activate", accel_group, gdk_keyval_from_name("q"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(cut_menu, "activate", accel_group, gdk_keyval_from_name("x"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(copy_menu, "activate", accel_group, gdk_keyval_from_name("c"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(paste_menu, "activate", accel_group, gdk_keyval_from_name("v"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(undo_menu, "activate", accel_group, gdk_keyval_from_name("z"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(redo_menu, "activate", accel_group, gdk_keyval_from_name("r"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(select_menu, "activate", accel_group, gdk_keyval_from_name("a"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(find_menu, "activate", accel_group, gdk_keyval_from_name("f"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(conv_menu, "activate", accel_group, gdk_keyval_from_name("b"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(exec_menu, "activate", accel_group, gdk_keyval_from_name("e"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
gtk_widget_add_accelerator(test_menu, "activate", accel_group, gdk_keyval_from_name("w"), GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE)
' Callbacks for the menu items
g_signal_connect_data(file_menu, "activate", Open_File, 0, 0, 0)
g_signal_connect_data(url_menu, "activate", Show_Dialog, g_Url_dialog, 0, 0)
g_signal_connect_data(save_menu, "activate", Save_File, 0, 0, 0)
g_signal_connect_data(saveas_menu, "activate", Save_Fileas, 0, 0, 0)
g_signal_connect_data(newtab_menu, "activate", Create_Page, 0, 0, 0)
g_signal_connect_data(opentab_menu, "activate", Open_Page, 0, 0, 0)
g_signal_connect_data(closetab_menu, "activate", Close_Tab, 0, 0, 0)
g_signal_connect_data(exit_menu, "activate", Exit_Prog, 0, 0, 0)
g_signal_connect_data(cut_menu, "activate", Cut_Text, 0, 0, 0)
g_signal_connect_data(copy_menu, "activate", Copy_Text, 0, 0, 0)
g_signal_connect_data(paste_menu, "activate", Paste_Text, 0, 0, 0)
g_signal_connect_data(undo_menu, "activate", Undo_Action, 0, 0, 0)
g_signal_connect_data(redo_menu, "activate", Redo_Action, 0, 0, 0)
g_signal_connect_data(select_menu, "activate", Select_All, 0, 0, 0)
g_signal_connect_data(find_menu, "activate", Start_Find, 0, 0, 0)
g_signal_connect_data(indent_menu, "activate", Set_Indent, 0, 0, 0)
g_signal_connect_data(linenr_menu, "activate", Set_Linenr, 0, 0, 0)
g_signal_connect_data(wrap_menu, "activate", Set_Wrapmode, 0, 0, 0)
g_signal_connect_data(font_menu, "activate", Show_Dialog, g_Font_dialog, 0, 0)
g_signal_connect_data(color_menu, "activate", Show_Dialog, g_Color_dialog, 0, 0)
g_signal_connect_data(menu_0, "activate", Set_Spacing, 0, 0, 0)
g_signal_connect_data(menu_1, "activate", Set_Spacing, 1, 0, 0)
g_signal_connect_data(menu_2, "activate", Set_Spacing, 2, 0, 0)
g_signal_connect_data(menu_3, "activate", Set_Spacing, 3, 0, 0)
g_signal_connect_data(menu_4, "activate", Set_Spacing, 4, 0, 0)
g_signal_connect_data(menu_5, "activate", Set_Spacing, 5, 0, 0)
g_signal_connect_data(syntax_menu, "activate", Get_Syntax, 0, 0, 0)
g_signal_connect_data(conv_menu, "activate", Show_Dialog, g_Options, 0, 0)
g_signal_connect_data(exec_menu, "activate", Show_Dialog, g_Execute, 0, 0)
g_signal_connect_data(test_menu, "activate", Show_Dialog, g_Test, 0, 0)
g_signal_connect_data(print_menu, "activate", Show_Dialog, g_Print_dialog, 0, 0)
g_signal_connect_data(help_menu, "activate", Handle_Help, 0, 0, 0)
g_signal_connect_data(about_menu, "activate", Show_Info, 0, 0, 0)
' Flag for Open_Tab
g_OPEN_PAGE = FALSE
'Endless mainloop
gtk_main
END SUB
'------------------------------------------------------------------------------------------------------------
SUB SYNC
WHILE gtk_events_pending() DO
gtk_main_iteration_do(FALSE)
WEND
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Disable_Console
gtk_widget_set_sensitive(g_Shell_label1, FALSE)
gtk_widget_set_sensitive(g_Shell_entry1, FALSE)
gtk_widget_set_sensitive(g_Shell_label2, FALSE)
gtk_widget_set_sensitive(g_Shell_entry2, FALSE)
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Enable_Console
gtk_widget_set_sensitive(g_Shell_label1, TRUE)
gtk_widget_set_sensitive(g_Shell_entry1, TRUE)
gtk_widget_set_sensitive(g_Shell_label2, TRUE)
gtk_widget_set_sensitive(g_Shell_entry2, TRUE)
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Execute_Binary(NUMBER widget, NUMBER dialog)
LOCAL cmd$, arg$, prog$, title$
gtk_widget_hide(dialog):SYNC
title$ = nbook[gtk_notebook_get_current_page(g_Notebook)].title$
prog$ = MID$(title$, 1, INSTRREV(title$, ".")-1)
IF gtk_toggle_button_get_active(con_radio) THEN
arg$ = gtk_entry_get_text(g_Shell_entry2)
arg$ = REPLACE$(arg$, CHR$(34), CONCAT$(CHR$(92), CHR$(34)) )
cmd$ = gtk_entry_get_text(g_Shell_entry1)
cmd$ = REPLACE$(cmd$, "@", CONCAT$(prog$, " ", arg$) )
ELSE
cmd$ = prog$
END IF
IF FILEEXISTS(prog$) THEN SYSTEM CONCAT$(cmd$, " &")
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Execute_Line(NUMBER widget, NUMBER statement)
LOCAL tmpdir$, cmd$
LOCAL tst TYPE FILE*
LOCAL iter1, iter2
' Save to tempdir
tmpdir$ = gtk_entry_get_text(g_Tmpdir_entry)
IF NOT(FILEEXISTS(tmpdir$)) THEN MAKEDIR tmpdir$
IF NOT(FILEEXISTS(tmpdir$)) THEN
CALL Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: temporary directory '", tmpdir$, "' does not exist!"), -1)
GOTO End_Sub
END IF
iter1 = MEMORY(DEFAULT_WIDGET_SIZE)
iter2 = MEMORY(DEFAULT_WIDGET_SIZE)
gtk_text_buffer_get_bounds(g_Test_buffer1, iter1, iter2)
cmd$ = gtk_text_buffer_get_text(g_Test_buffer1, iter1, iter2, 1)
FREE iter1
FREE iter2
OPEN CONCAT$(tmpdir$, g_BACONSHELL$) FOR WRITING AS tst
WRITELN cmd$ TO tst
CLOSE FILE tst
' Compile Run and set output
CALL Convert_Source(0, 0)
' Delete files if no error occured
IF FILEEXISTS(CONCAT$(tmpdir$, g_BACONSHELL$)) THEN DELETE FILE CONCAT$(tmpdir$, g_BACONSHELL$)
IF FILEEXISTS(CONCAT$(tmpdir$, LEFT$(g_BACONSHELL$, INSTRREV(g_BACONSHELL$, ".")-1) )) THEN DELETE FILE CONCAT$(tmpdir$, LEFT$(g_BACONSHELL$, INSTRREV(g_BACONSHELL$, ".")-1) )
LABEL End_Sub
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Clear_Test_Area
gtk_text_buffer_set_text(g_Test_buffer2, "", -1)
END SUB
'------------------------------------------------------------------------------------------------------------
SUB Start_Shell
LOCAL dir$, cmd$
IF INSTR(OS$, "Darwin") THEN
cmd$ = "/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal"
ELSE
cmd$ = gtk_entry_get_text(g_Shell_entry1)
END IF
' This is the current sourcefile
dir$ = nbook[gtk_notebook_get_current_page(g_Notebook)].title$
' Change the working directory
IF LEN(dir$) > 0 THEN CHANGEDIR MID$(dir$, 1, INSTRREV(dir$, "/")-1)
IF INSTR(cmd$, " ") THEN
SYSTEM CONCAT$(MID$(cmd$, 1, INSTR(cmd$, " ")-1), " &")
ELSE
SYSTEM CONCAT$(cmd$, " &")
END IF
END SUB
'------------------------------------------------------------------------------------------------------------
FUNCTION Run_Dialog(NUMBER type, NUMBER buttons, STRING message$, NUMBER line)
LOCAL dialog, response, buffer, view, mark, iter
IF line > 0 THEN
buffer = nbook[gtk_notebook_get_current_page(g_Notebook)].buffer
view = nbook[gtk_notebook_get_current_page(g_Notebook)].view
iter = MEMORY(DEFAULT_WIDGET_SIZE)
gtk_text_buffer_get_iter_at_line(buffer, iter, line-1)
mark = gtk_text_buffer_create_mark(buffer, "mark", iter, 0)
gtk_text_view_scroll_to_mark(view, mark, 0, 1, 0.5, 0.5)
gtk_text_buffer_place_cursor(buffer, iter)
gtk_source_view_set_highlight_current_line(view, 1)
gtk_text_buffer_delete_mark(buffer, mark)
FREE iter
END IF
dialog = gtk_message_dialog_new(g_Win, GTK_DIALOG_DESTROY_WITH_PARENT, type, buttons, "%s", message$, NULL)
gtk_window_set_transient_for(dialog, g_Win)
gtk_window_set_position(dialog, GTK_WIN_POS_CENTER_ON_PARENT)
IF buttons = GTK_BUTTONS_YES_NO THEN gtk_dialog_set_default_response(dialog, GTK_RESPONSE_YES)
SELECT type
CASE GTK_MESSAGE_ERROR
gtk_window_set_title(dialog, "Error")
gtk_window_set_icon_name(dialog, "gtk-dialog-error")
CASE GTK_MESSAGE_WARNING
gtk_window_set_title(dialog, "Warning")
gtk_window_set_icon_name(dialog, "gtk-dialog-warning")
CASE GTK_MESSAGE_INFO
gtk_window_set_title(dialog, "Informational")
gtk_window_set_icon_name(dialog, "gtk-dialog-info")
DEFAULT
gtk_window_set_title(dialog, "Message")
gtk_window_set_icon_name(dialog, "gtk-about")
END SELECT
response = gtk_dialog_run(dialog)
gtk_widget_destroy(dialog)
RETURN response
END FUNCTION
'------------------------------------------------------------------------------------------------------------
'------------------------------------------------------------------------------------------------------------
'------------------------------------------------------------------------------------------------------------
FUNCTION Check_Declared(STRING filename$, STRING v$, NUMBER position)
LOCAL txt$, needle$
LOCAL expr
LOCAL thefile TYPE FILE*
needle$ = REPLACE$(v$, "*", "\\*")
OPEN filename$ FOR READING AS thefile
SEEK thefile OFFSET position
WHILE NOT(ENDFILE(thefile)) DO
READLN txt$ FROM thefile
IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 AND NOT(INSTR(txt$, " noparse ")) THEN
expr = REGEX(txt$, "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING")
IF ISTRUE(expr) THEN
IF INSTR(needle$, "[") THEN
expr = REGEX(txt$, CONCAT$(" ", LEFT$(needle$, INSTR(needle$, "[")-1), "\\[|,", LEFT$(needle$, INSTR(needle$, "[")-1), "\\[" ))
ELSE
expr = REGEX(txt$, CONCAT$(" ", needle$, ",| ", needle$, ";|\\*", needle$, " |,", needle$, ",|,", needle$, ";| ", needle$, " +=|\\*", needle$, ";"))
END IF
IF ISTRUE(expr) THEN BREAK
ENDIF
ENDIF
WEND
CLOSE FILE thefile
RETURN expr
END FUNCTION
'----------------------------------------------------------------------------------------------
FUNCTION Check_Type$(STRING filename$, STRING v$, NUMBER position)
LOCAL txt$, needle$
LOCAL expr
LOCAL thefile TYPE FILE*
needle$ = CHOP$(REPLACE$(v$, "*", "\\*"))
OPEN filename$ FOR READING AS thefile
SEEK thefile OFFSET position
WHILE NOT(ENDFILE(thefile)) DO
READLN txt$ FROM thefile
IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 AND NOT(INSTR(txt$, " noparse ")) THEN
expr = REGEX(txt$, "DIR|FILE|int|long|float|double|char|void|STRING|NUMBER|FLOATING")
IF ISTRUE(expr) THEN
IF INSTR(needle$, "[") THEN
IF INSTR(needle$, g_STRINGSIGN$) THEN
expr = REGEX(txt$, CONCAT$(" *", LEFT$(needle$, INSTR(needle$, "[")-1), "\\["))
ELSE
expr = REGEX(txt$, CONCAT$(" ", LEFT$(needle$, INSTR(needle$, "[")-1), "\\["))
ENDIF
ELSE
expr = REGEX(txt$, CONCAT$(" ", needle$, ",| ", needle$, ";|,", needle$, ",|,", needle$, ";| ", needle$, " +="))
END IF
IF ISTRUE(expr) THEN BREAK
ENDIF
ENDIF
WEND
CLOSE FILE thefile
IF ISTRUE(expr) THEN RETURN txt$
RETURN ""
END FUNCTION
'----------------------------------------------------------------------------------------------
FUNCTION Search(STRING file$, STRING line$, NUMBER position)
LOCAL found
LOCAL txt$
LOCAL handle TYPE FILE*
found = -1
OPEN file$ FOR READING AS handle
SEEK handle OFFSET position
WHILE NOT(ENDFILE(handle)) DO
READLN txt$ FROM handle
IF INSTR(txt$, line$) THEN
found = TRUE
BREAK
ENDIF
WEND
CLOSE FILE handle
RETURN found
END FUNCTION
'----------------------------------------------------------------------------------------------
SUB Print_Element (STRING arg$)
LOCAL len, check
' Get part just before '('
len = INSTR(arg$, "(")-1
IF len < 0 THEN len = LEN(arg$)
' Check on string by reference variable
check = Search(g_HFILE$, CONCAT$("char *", arg$, " = NULL;"), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
check = Search(g_CFILE$, CONCAT$("char *", arg$, " = NULL;"), 0)
ENDIF
' Check if var is string var
IF INSTR(MID$(arg$, 1, len), g_STRINGSIGN$) OR INSTR(MID$(arg$, 1, len), CHR$(34)) OR REGEX(MID$(arg$, 1, len), "gettext|ngettext") OR check >= 0 THEN
WRITELN "__b2c__assign = ", arg$, "; if(__b2c__assign != NULL) fprintf(stdout, \"%s\", __b2c__assign);" TO g_CFILE
ELSE
WRITELN "fprintf(stdout, \"%s\", STR", g_STRINGSIGN$, "(", arg$, "));" TO g_CFILE
END IF
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Print(STRING arg$)
LOCAL exp$, form$, to$
LOCAL x, in_string, in_func, pos, escaped, check
' Check if argument
IF ISTRUE(LEN(arg$)) THEN
' Omit semicolon if there is one
IF EQUAL(RIGHT$(arg$, 1), ";") THEN
exp$ = LEFT$(arg$, LEN(arg$) - 1)
ELSE
exp$ = arg$
END IF
' If there is a FORMAT argument
IF INSTR(exp$, " FORMAT ") THEN
form$ = MID$(exp$, INSTR(exp$, " FORMAT ") + 8)
' Optional TO argument?
IF INSTR(form$, " TO ") THEN
to$ = MID$(form$, INSTR(form$, " TO ") + 4)
' Check if variable is declared
IF NOT(REGEX(to$, "\\[.*\\]")) THEN
check = Search(g_HFILE$, CONCAT$("char *", to$, " = NULL;"), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
check = Search(g_CFILE$, CONCAT$("char *", to$, " = NULL;"), 0)
ENDIF
IF check < 0 THEN WRITELN "char *", to$, " = NULL;" TO g_HFILE
END IF
WRITELN to$, " = (char*)realloc(", to$, ", (", g_BUFFER_SIZE, "+1)*sizeof(char));" TO g_CFILE
WRITELN "snprintf(", to$, ", ", g_BUFFER_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$)
IF EQUAL(MID$(exp$, x, 1), ",") THEN
IF ISFALSE(in_string) AND ISFALSE(in_func) THEN
Print_Element(CHOP$(MID$(exp$, pos, x-pos)))
pos = x + 1
escaped = FALSE
END IF
ELIF EQUAL(MID$(exp$, x, 1), "\\") THEN
escaped = TRUE
ELIF EQUAL(MID$(exp$, x, 1), CHR$(34)) THEN
IF ISFALSE(escaped) THEN
in_string = NOT(in_string)
END IF
escaped = FALSE
ELIF EQUAL(MID$(exp$, x, 1), "(") THEN
IF ISFALSE(in_string) THEN
INCR in_func
END IF
escaped = FALSE
ELIF EQUAL(MID$(exp$, x, 1), ")") THEN
IF ISFALSE(in_string) THEN
DECR in_func
END IF
escaped = FALSE
ELSE
escaped = FALSE
ENDIF
NEXT
Print_Element(CHOP$(MID$(exp$, pos)))
' If line ends with ';' then skip newline
IF ISFALSE(EQUAL(RIGHT$(arg$, 1), ";")) THEN
WRITELN "fprintf(stdout, \"\\n\");" TO g_CFILE
END IF
END IF
ELSE
WRITELN "fprintf(stdout, \"\\n\");" TO g_CFILE
END IF
' Flush print buffer
WRITELN "fflush(stdout);" TO g_CFILE
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Input(STRING arg$)
LOCAL x, in_string, in_func, pos, check, escaped
LOCAL type$
' Check if we have an argument at all
IF ISFALSE(LEN(arg$)) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty INPUT at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Start miniparser
in_string = FALSE
in_func = 0
pos = 1
escaped = 0
FOR x = 1 TO LEN(arg$)
IF ISTRUE(EQUAL(MID$(arg$, x, 1), ",")) THEN
IF ISFALSE(in_string) AND ISFALSE(in_func) THEN
Print_Element(CHOP$(MID$(arg$, pos, x-pos)))
pos = x+1
escaped = FALSE
END IF
ELIF EQUAL(MID$(arg$, x, 1), "\\") THEN
escaped = TRUE
ELIF ISTRUE(EQUAL(MID$(arg$, x, 1), CHR$(34))) THEN
IF ISFALSE(escaped) THEN
in_string = NOT(in_string)
END IF
escaped = FALSE
ELIF ISTRUE(EQUAL(MID$(arg$, x, 1), "(")) THEN
IF ISFALSE(in_string) THEN
INCR in_func
END IF
escaped = FALSE
ELIF ISTRUE(EQUAL(MID$(arg$, x, 1), ")")) THEN
IF ISFALSE(in_string) THEN
DECR in_func
END IF
escaped = FALSE
ELSE
escaped = FALSE
ENDIF
NEXT
arg$ = CHOP$(MID$(arg$, pos))
' Check type of var, string?
IF INSTR(arg$, g_STRINGSIGN$) THEN
IF NOT(REGEX(arg$, "\\[.*\\]")) THEN
' Is variable declared already?
check = Search(g_HFILE$, CONCAT$("char *", arg$, " = NULL;"), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
check = Search(g_CFILE$, CONCAT$("char *", arg$, " = NULL;"), 0)
ENDIF
IF check < 0 THEN WRITELN "char *", arg$, " = NULL;" TO g_HFILE
END IF
' Translate function to C function
WRITELN "__b2c__counter = 1; do{ memset(__b2c__input__buffer, '\\0', ", g_BUFFER_SIZE, ");" TO g_CFILE
WRITELN "__b2c__assign = fgets(__b2c__input__buffer, ", g_BUFFER_SIZE, ", stdin);" TO g_CFILE
' Make sure internal var is copied to var of program
WRITELN arg$, " = (char*)realloc(", arg$, ", (", g_BUFFER_SIZE, "+1)*__b2c__counter*sizeof(char));" TO g_CFILE
WRITELN "if(__b2c__counter == 1) strncpy(", arg$, ", __b2c__input__buffer, ", g_BUFFER_SIZE, ");" TO g_CFILE
WRITELN "else strncat(", arg$, ", __b2c__input__buffer, ", g_BUFFER_SIZE, "); __b2c__counter++;" TO g_CFILE
WRITELN "} while (!strstr(__b2c__input__buffer, \"\\n\") && strlen(__b2c__input__buffer));" TO g_CFILE
' Cut off last newline
WRITELN "if (strlen(__b2c__input__buffer))", arg$, "[strlen(", arg$, ")-1] = '\\0';" TO g_CFILE
' Var is numeric or stringarray
ELSE
' Variable may not be array, these should be defined with DECLARE
IF NOT(REGEX(arg$, "\\[.*\\]")) AND NOT(INSTR(arg$, ".")) THEN
' Is variable declared already?
check = Check_Declared(g_HFILE$, arg$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, arg$, 0)
IF ISFALSE(check) THEN WRITELN "long ", arg$, ";" TO g_HFILE
END IF
' Get the type
type$ = Check_Type$(g_HFILE$, arg$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN
type$ = Check_Type$(g_CFILE$, arg$, 0)
END IF
' Translate function to C function - we do not need endless buffer here because numbers never can have more than 10 digits anyway
WRITELN "memset(__b2c__input__buffer, '\\0', ", g_BUFFER_SIZE, "); __b2c__assign = fgets(__b2c__input__buffer, ", g_BUFFER_SIZE, ", stdin);" TO g_CFILE
' Make sure internal var is copied to var of program
IF INSTR(type$, "double ") OR INSTR(type$, "float ") OR INSTR(type$, "FLOATING ") THEN
WRITELN arg$, " = atof(__b2c__input__buffer);" TO g_CFILE
ELIF INSTR(type$, "long ") OR INSTR(type$, "NUMBER ") THEN
WRITELN arg$, " = atol(__b2c__input__buffer);" TO g_CFILE
ELSE
WRITELN arg$, " = atoi(__b2c__input__buffer);" TO g_CFILE
END IF
END IF
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_For(STRING arg$)
LOCAL var$, tmp$, from$, to$, step$
LOCAL check
' Get the variablename without (surrounding) spaces
var$ = CHOP$(LEFT$(arg$, INSTR(arg$, "=") - 1))
tmp$ = CHOP$(MID$(arg$, INSTR(arg$, "=") + 1))
' Do we have a STRING var?
IF INSTR(var$, g_STRINGSIGN$) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: variable in FOR statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "' cannot be string!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check if TO is available
IF NOT(INSTR(tmp$, " TO ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing TO in FOR statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the starting and ending value
from$ = CHOP$(LEFT$(tmp$, INSTR(tmp$, " TO ") - 1))
to$ = CHOP$(MID$(tmp$, INSTR(tmp$, " TO ") + 3))
' Check if there is a STEP
IF ISTRUE(INSTR(to$, " STEP ")) THEN
step$ = CHOP$(MID$(to$, INSTR(to$, " STEP ") + 5))
to$ = CHOP$(LEFT$(to$, INSTR(to$, " STEP ") - 1))
ELSE
step$ = "1"
END IF
' Variable may not be array, these should be defined with DECLARE
IF NOT(REGEX(var$, "\\[.*\\]")) AND ISFALSE(INSTR(var$, ".")) THEN
' Is variable declared already?
check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, var$, 0)
IF ISFALSE(check) THEN WRITELN "long ", var$, ";" TO g_HFILE
END IF
' Translate function to C function
IF VAL(step$) < 0 THEN
WRITELN "for(", var$," = ", from$, "; ", var$, " >= ", to$, ";", var$, " += ", step$, "){" TO g_CFILE
ELSE
WRITELN "for(", var$," = ", from$, "; ", var$, " <= ", to$, ";", var$, " += ", step$, "){" TO g_CFILE
END IF
LABEL End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: Endless recursion in RELATE statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Now add relation
FOR ctr = 0 TO g_RELATE_CTR
IF EQUAL(LEFT$(g_RELATE$[ctr], LEN(var$)), var$) THEN
rel$ = MID$(g_RELATE$[ctr], INSTR(g_RELATE$[ctr], " ")+1)
WRITELN "if(__b2c__", rel$, "_exist (", str$, " == NULL) __b2c__", rel$, "__add(", str$, ";" TO g_CFILE
IF INSTR(rel$, g_STRINGSIGN$) THEN
WRITELN "__b2c__", rel$, "_exist(", str$, "->value = realloc(__b2c__", rel$, "_exist(", str$, "->value, (strlen(", tmp$, ")+1)*sizeof(char));" TO g_CFILE
WRITELN "strcpy(__b2c__", rel$, "_exist(", str$, "->value, ", tmp$, ");" TO g_CFILE
ELSE
WRITELN "__b2c__", rel$, "_exist(", str$, "->value = ", tmp$, ";" TO g_CFILE
END IF
Relate_Recurse(rel$, str$, tmp$, lvl)
END IF
NEXT
LABEL End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: could not parse line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the variablename without surrounding spaces
var$ = CHOP$(LEFT$(arg$, INSTR(arg$, "=") - 1))
tmp$ = CHOP$(MID$(arg$, INSTR(arg$, "=") + 1))
' Check if var is string var, exclude RECORD elements
IF REGEX(var$, CONCAT$(g_STRINGSIGN$, "$")) AND NOT(INSTR(var$, ".")) THEN
' Is variable declared already?
check = Search(g_HFILE$, CONCAT$("char *", var$, " = NULL;"), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
check = Search(g_CFILE$, CONCAT$("char *", var$, " = NULL;"), 0)
ENDIF
IF check < 0 AND NOT(REGEX(g_PROTOTYPE$, CONCAT$(".* ", var$, "[ ,)]+"))) THEN
WRITELN "char *", var$, " = NULL;" TO g_HFILE
END IF
' Assume number, exclude RECORD elements
ELIF NOT(REGEX(var$, "\\[.*\\]")) AND NOT(INSTR(var$, ".")) AND NOT(EQUAL(var$, "ERROR")) AND NOT(EQUAL(var$, "RETVAL")) AND NOT(REGEX(var$, "\\(.*\\)")) THEN
' Is variable declared already?
check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, var$, 0)
IF ISFALSE(check) AND NOT(REGEX(g_PROTOTYPE$, CONCAT$(".* ", var$, "[ ,)]+"))) THEN
IF INSTR(tmp$, ".") AND NOT(INSTR(tmp$, CHR$(34))) THEN WRITELN "double ", var$, ";" TO g_HFILE
ELSE WRITELN "long ", var$, ";" TO g_HFILE
END IF
END IF
' Check if there is associative array assignment
IF REGEX(var$, "\\(.*\\)$") THEN
lft$ = LEFT$(var$, INSTR(var$, "(") - 1)
str$ = MID$(var$, INSTR(var$, "(") + 1)
WRITELN "if(__b2c__", lft$, "_exist (", str$, " == NULL) __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
IF INSTR(lft$, g_STRINGSIGN$) THEN
WRITELN "__b2c__", lft$, "_exist(", str$, "->value = realloc(__b2c__", lft$, "_exist(", str$, "->value, (strlen(", tmp$, ")+1)*sizeof(char));" TO g_CFILE
WRITELN "strcpy(__b2c__", lft$, "_exist(", str$, "->value, ", tmp$, ");" TO g_CFILE
ELSE
WRITELN "__b2c__", lft$, "_exist(", str$, "->value = ", tmp$, ";" TO g_CFILE
END IF
' Check for relations
Relate_Recurse(lft$, str$, tmp$, -1)
' Do we have a STRING variable or STRING array?
ELIF INSTR(var$, g_STRINGSIGN$) AND NOT(REGEX(var$, CONCAT$(".*\\[.*", g_STRINGSIGN$, ".*\\].*"))) THEN
WRITELN "__b2c__assign = (char*) strdup (", tmp$, "); ", g_WITHVAR$, var$, " = (char*)realloc(", g_WITHVAR$, var$, ", (strlen(__b2c__assign)+1)*sizeof(char));" TO g_CFILE
WRITELN "strcpy(", g_WITHVAR$, var$, ", __b2c__assign); free(__b2c__assign);" TO g_CFILE
' Also check if string var already is used for IMPORT, if so, perform dlopen again
ptr$ = REPLACE$(REPLACE$(var$, CHR$(34), ""), "-", "")
ptr$ = REPLACE$(REPLACE$(REPLACE$(ptr$, ".", ""), "/", ""), "_", "")
check = Search(g_CFILE$, CONCAT$("void* __b2c__dlopen__pointer_", ptr$, ";"), 0)
IF check >= 0 THEN
WRITELN "__b2c__dlopen__pointer_", ptr$, " = dlopen(", var$, ", RTLD_LAZY);" TO g_CFILE
END IF
ELSE
WRITELN g_WITHVAR$, arg$, ";" TO g_CFILE
END IF
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Open(STRING arg$)
LOCAL check
LOCAL file$, tmp$, mode$, handle$
' Check if FOR is available
IF NOT(INSTR(arg$, " FOR ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing FOR in OPEN statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check if AS is available
IF NOT(INSTR(arg$, " AS ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing AS in OPEN statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the file, mode and handle
file$ = CHOP$(LEFT$(arg$, INSTR(arg$, " FOR ") - 1))
tmp$ = CHOP$(MID$(arg$, INSTR(arg$, " FOR ") + 5))
mode$ = CHOP$(LEFT$(tmp$, INSTR(tmp$, " AS ") - 1))
handle$ = CHOP$(MID$(tmp$, INSTR(tmp$, " AS ") + 4))
' Check if var is string var
IF INSTR(handle$, g_STRINGSIGN$) AND NOT(EQUAL(mode$, "MEMORY")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: variable for OPEN at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "' cannot be string!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check if variable was declared
IF NOT(INSTR(handle$, ".")) THEN
check = Check_Declared(g_HFILE$, handle$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, handle$, 0)
END IF
' File or dir?
IF EQUAL(mode$, "DIRECTORY") THEN
IF ISFALSE(check) THEN
WRITELN "DIR* ", handle$, ";" TO g_HFILE
END IF
ELIF EQUAL(mode$, "MEMORY") THEN
IF ISFALSE(check) THEN
WRITELN "char* ", handle$, ";" TO g_HFILE
END IF
check = Check_Declared(g_HFILE$, CONCAT$("__b2c_mem_", handle$, ";"), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, CONCAT$("__b2c_mem_", handle$, ";"), 0)
IF ISFALSE(check) THEN
WRITELN "long __b2c_mem_", handle$, ";" TO g_HFILE
END IF
ELIF EQUAL(mode$, "NETWORK") OR EQUAL(mode$, "SERVER") OR EQUAL(mode$, "UDP") THEN
IF ISFALSE(check) THEN
WRITELN "int ", handle$, ";" TO g_HFILE
END IF
ELSE
IF ISFALSE(check) THEN
WRITELN "FILE* ", handle$, ";" TO g_HFILE
END IF
END IF
' Convert to C syntax
IF EQUAL(mode$, "READING") THEN
WRITELN handle$, " = fopen(", file$, ", \"r\");" TO g_CFILE
WRITELN "if(", handle$, " == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
ELIF EQUAL(mode$, "WRITING") THEN
WRITELN handle$, " = fopen(", file$, ", \"w\");" TO g_CFILE
WRITELN "if(", handle$, " == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
ELIF EQUAL(mode$, "APPENDING") THEN
WRITELN handle$, " = fopen(", file$, ", \"a\");" TO g_CFILE
WRITELN "if(", handle$, " == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
ELIF EQUAL(mode$, "READWRITE") THEN
WRITELN handle$, " = fopen(", file$, ", \"r+\");" TO g_CFILE
WRITELN "if(", handle$, " == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
ELIF EQUAL(mode$, "DIRECTORY") THEN
WRITELN handle$, " = opendir(", file$, ");" TO g_CFILE
WRITELN "if(", handle$, " == NULL){if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set) {fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
ELIF EQUAL(mode$, "MEMORY") THEN
WRITELN handle$, " = (char*)", file$, "; __b2c_mem_", handle$, " = ", file$, ";" TO g_CFILE
WRITELN "if(!__b2c__trap){if(__b2c__memory__check(", handle$, ")) {ERROR=1; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
ELIF EQUAL(mode$, "NETWORK") THEN
' Network code
WRITELN "if (strstr(", file$, ", \":\") == NULL){ERROR = 10; fprintf(stderr, \"ERROR: %s: '%s'\\n\", ERR", g_STRINGSIGN$, "(ERROR), ", file$, "); exit(ERROR);}" TO g_CFILE
WRITELN "strncpy(__b2c__data_client, ", file$, ", ", g_BUFFER_SIZE, ");__b2c__host = strtok(__b2c__data_client, \":\"); __b2c__port = strtok(NULL, \":\");__b2c__he = gethostbyname(__b2c__host);" TO g_CFILE
WRITELN "if (__b2c__he == NULL || __b2c__he->h_addr == NULL) {if(!__b2c__trap){ERROR = 11;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
WRITELN handle$, " = socket(AF_INET, ", g_SOCKTYPE$, ", 0);" TO g_CFILE
WRITELN "if (", handle$, " == -1) {if(!__b2c__trap){ERROR = 12;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
WRITELN "__b2c__to.tv_sec = ", g_OPTION_SOCKET, "; __b2c__to.tv_usec = 0; setsockopt(", handle$, ", SOL_SOCKET, SO_SNDTIMEO, &__b2c__to, sizeof(struct timeval));" TO g_CFILE
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
ENDIF
WRITELN "setsockopt(", handle$, ", SOL_SOCKET, SO_REUSEADDR, &__b2c__yes, sizeof(int)); __b2c__addr.sin_family = AF_INET; __b2c__addr.sin_port = htons((long)atol(__b2c__port));" TO g_CFILE
WRITELN "__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr); memset(&(__b2c__addr.sin_zero), '\\0', sizeof(__b2c__addr.sin_zero));" TO g_CFILE
WRITELN "__b2c__result = connect(", handle$, ", (struct sockaddr *)&__b2c__addr, sizeof(struct sockaddr));" TO g_CFILE
WRITELN "if(__b2c__result == -1) {if(!__b2c__trap){ERROR = 13;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
ELIF EQUAL(mode$, "SERVER") THEN
' Network code
WRITELN "if (strstr(", file$, ", \":\") == NULL){ERROR = 10; fprintf(stderr, \"ERROR: %s: '%s'\\n\", ERR", g_STRINGSIGN$, "(ERROR), ", file$, "); exit(ERROR);}" TO g_CFILE
WRITELN "if(strcmp(__b2c__data_server, ", file$, ")) {strncpy(__b2c__data_server, ", file$, ", ", g_BUFFER_SIZE, ");__b2c__host = strtok(__b2c__data_server, \":\"); __b2c__port = strtok(NULL, \":\");__b2c__he = gethostbyname(__b2c__host);" TO g_CFILE
WRITELN "if (__b2c__he == NULL || __b2c__he->h_addr == NULL) {if(!__b2c__trap){ERROR = 11;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
WRITELN "__b2c__handle = socket(AF_INET, ", g_SOCKTYPE$, ", 0);" TO g_CFILE
WRITELN "if (__b2c__handle == -1) {if(!__b2c__trap){ERROR = 12;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
WRITELN "__b2c__to.tv_sec = ", g_OPTION_SOCKET, "; __b2c__to.tv_usec = 0; setsockopt(__b2c__handle, SOL_SOCKET, SO_SNDTIMEO, &__b2c__to, sizeof(struct timeval));" TO g_CFILE
WRITELN "setsockopt(__b2c__handle, SOL_SOCKET, SO_REUSEADDR, &__b2c__yes, sizeof(int));__b2c__addr.sin_family = AF_INET; __b2c__addr.sin_port = htons((long)atol(__b2c__port));" TO g_CFILE
WRITELN "__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr);memset(&(__b2c__addr.sin_zero), '\\0', sizeof(__b2c__addr.sin_zero));" TO g_CFILE
WRITELN "__b2c__result = bind(__b2c__handle, (struct sockaddr *)&__b2c__addr, sizeof(struct sockaddr));" TO g_CFILE
WRITELN "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 17;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
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){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
WRITELN "strncpy(__b2c__data_server, ", file$, ", ", g_BUFFER_SIZE, "); /* Restore data because of strtok */} __b2c__result = accept(__b2c__handle, NULL, 0);" TO g_CFILE
WRITELN "if(__b2c__result == -1){if(!__b2c__trap){ERROR = 19;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
WRITELN handle$, "= __b2c__result;" TO g_CFILE
END IF
END IF
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Seek(STRING arg$)
LOCAL dim
' Check if we have an argument at all
IF ISFALSE(LEN(arg$)) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty SEEK at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check if OFFSET is available
IF NOT(INSTR(arg$, " OFFSET ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing OFFSET in SEEK statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the variablename, filedescriptor
SPLIT arg$ BY " " TO element$ SIZE dim
' Convert to C function
IF dim EQ 3 THEN
WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_SET);" TO g_CFILE
ELIF dim EQ 5 THEN
IF EQUAL(element$[5], "START") THEN
WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_SET);" TO g_CFILE
ELIF EQUAL(element$[4], "CURRENT") THEN
WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_CUR);" TO g_CFILE
ELIF EQUAL(element$[4], "END") THEN
WRITELN "fseek(", element$[1], ", ", element$[3], ", SEEK_END);" TO g_CFILE
END IF
ELSE
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: erroneous SEEK statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
END IF
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Copy(STRING arg$)
LOCAL from$, to$
' Check if we have an argument at all
IF ISFALSE(LEN(arg$)) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty COPY at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check if TO is available
IF NOT(INSTR(arg$, " TO ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: Missing TO in COPY statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the filename and copyname
from$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " TO ") - 1))
to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4))
' Translate to C function
WRITELN "__b2c__inFile = fopen(", from$, ", \"r\"); __b2c__outFile = fopen(", to$, ", \"w\"); __b2c__Byte = 0;" TO g_CFILE
WRITELN "if (__b2c__inFile != NULL && __b2c__outFile != NULL){while(__b2c__Byte!=EOF){" TO g_CFILE
WRITELN "__b2c__Byte=fgetc(__b2c__inFile); if(__b2c__Byte!=EOF){" TO g_CFILE
WRITELN "fputc(__b2c__Byte,__b2c__outFile); }}" TO g_CFILE
WRITELN "fclose(__b2c__inFile); fclose(__b2c__outFile);}" TO g_CFILE
WRITELN "else { if(!__b2c__trap){ERROR = 2; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Rename(STRING arg$)
LOCAL from$, to$
' Check if we have an argument at all
IF ISFALSE(LEN(arg$)) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty RENAME at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check if TO is available
IF NOT(INSTR(arg$, " TO ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: Missing TO in RENAME statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the filename and copyname
from$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " TO ") - 1))
to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4))
' Translate to C function
WRITELN "if(rename(", from$, ", ", to$, ") < 0) {if(!__b2c__trap){ERROR = 9; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Readln(STRING arg$)
LOCAL dim, check
' Check if FROM is available
IF NOT(INSTR(arg$, " FROM ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing FROM in READLN statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: variable for READLN at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "' must be string!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check if var is string var, exclude RECORD elements
IF NOT(REGEX(element$[1], "\\[.*\\]")) THEN
' Is variable declared already?
check = Search(g_HFILE$, CONCAT$("char *", element$[1], " = NULL;"), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
check = Search(g_CFILE$, CONCAT$("char *", element$[1], " = NULL;"), 0)
ENDIF
IF check < 0 THEN WRITELN "char *", element$[1], " = NULL;" TO g_HFILE
END IF
' Translate function to C function
WRITELN "__b2c__counter = 1; do{ memset(__b2c__input__buffer, '\\0', ", g_BUFFER_SIZE, ");" TO g_CFILE
WRITELN "__b2c__assign = fgets(__b2c__input__buffer, ", g_BUFFER_SIZE, ", ", element$[3], ");" TO g_CFILE
' Make sure internal var is copied to var of program
WRITELN element$[1], " = (char*)realloc(", element$[1], ", (", g_BUFFER_SIZE, "+1)*__b2c__counter*sizeof(char));" TO g_CFILE
WRITELN "if(__b2c__counter == 1) strncpy(", element$[1], ", __b2c__input__buffer, ", g_BUFFER_SIZE, ");" TO g_CFILE
WRITELN "else strncat(", element$[1], ", __b2c__input__buffer, ", g_BUFFER_SIZE, "); __b2c__counter++;" TO g_CFILE
WRITELN "} while (!strstr(__b2c__input__buffer, \"\\n\") && strlen(__b2c__input__buffer));" TO g_CFILE
' Cut off last newline
WRITELN "if (strlen(__b2c__input__buffer))", element$[1], "[strlen(", element$[1], ")-1]='\\0';" TO g_CFILE
' Cut off CR if available
WRITELN "if(strlen(", element$[1], ")>0 && ", element$[1], "[strlen(", element$[1], ")-1]=='\\r') ", element$[1], "[strlen(", element$[1], ")-1]='\\0';" TO g_CFILE
LABEL End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing TO in WRITELN statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the variablename, filedescriptor
var$ = LEFT$(arg$, INSTRREV(arg$, " TO "))
to$ = CHOP$(MID$(arg$, INSTRREV(arg$, " TO ") + 4))
' Start miniparser
in_string = FALSE
in_func = 0
pos = 1
escaped = 0
FOR x = 1 TO LEN(var$)
IF ISTRUE(EQUAL(MID$(var$, x, 1), ",")) THEN
IF ISFALSE(in_string) AND ISFALSE(in_func) THEN
len = INSTR(MID$(var$, pos, x-pos), "(")-1
IF len < 0 THEN len = x-pos
IF INSTR(MID$(var$, pos, len), g_STRINGSIGN$) OR INSTR(MID$(var$, pos, len), CHR$(34)) THEN
WRITELN "fprintf(", to$, ", \"%s\", ", MID$(var$, pos, x-pos), ");" TO g_CFILE
ELSE
WRITELN "fprintf(", to$, ", \"%s\", STR", g_STRINGSIGN$, "(", MID$(var$, pos, x-pos), "));" TO g_CFILE
END IF
pos = x+1
escaped = FALSE
END IF
ELIF EQUAL(MID$(var$, x, 1), "\\") THEN
escaped = TRUE
ELIF ISTRUE(EQUAL(MID$(var$, x, 1), CHR$(34))) THEN
IF ISFALSE(escaped) THEN
in_string = NOT(in_string)
END IF
escaped = FALSE
ELIF ISTRUE(EQUAL(MID$(var$, x, 1), "(")) THEN
IF ISFALSE(in_string) THEN
INCR in_func
END IF
escaped = FALSE
ELIF ISTRUE(EQUAL(MID$(var$, x, 1), ")")) THEN
IF ISFALSE(in_string) THEN
DECR in_func
END IF
escaped = FALSE
ELSE
escaped = FALSE
ENDIF
NEXT
var$ = MID$(var$, pos)
' Write last element to file
len = INSTR(var$, "(")-1
IF len < 0 THEN len = LEN(var$)
IF INSTR(LEFT$(var$, len), g_STRINGSIGN$) OR INSTR(LEFT$(var$, len), CHR$(34)) THEN
WRITELN "fprintf(", to$, ", \"%s\\n\", ", var$, ");" TO g_CFILE
ELSE
WRITELN "fprintf(", to$, ", \"%s\\n\", STR", g_STRINGSIGN$, "(", var$, "));" TO g_CFILE
END IF
WRITELN "fflush(", to$, ");" TO g_CFILE
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Getbyte(STRING arg$)
LOCAL dim, check
LOCAL var$, to$, size$
' Check if FROM is available
IF NOT(INSTR(arg$, " FROM ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing FROM in GETBYTE statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the variablename, filedescriptor
var$ = CHOP$(LEFT$(arg$, INSTRREV(arg$, " FROM ")))
to$ = CHOP$(MID$(arg$, INSTRREV(arg$, " FROM ") + 6))
' Check if SIZE is available
IF INSTR(to$, " SIZE ") THEN
size$ = MID$(to$, INSTR(to$, " SIZE ") + 6)
to$ = MID$(to$, 1, INSTR(to$, " SIZE "))
ELSE
size$ = "1"
END IF
' Declare variable if not done yet, assuming long
IF NOT(INSTR(var$, ".")) THEN
check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, var$, 0)
IF ISFALSE(check) THEN WRITELN "long ", var$, ";" TO g_HFILE
END IF
' Translate function to C function
WRITELN "if(!__b2c__trap){if(__b2c__memory__check((char *)", var$, ")) {ERROR=1; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
WRITELN "__b2c__counter = fread((void*)", var$, ", sizeof(", g_OPTION_MEMTYPE$, "), ", size$, ", ", to$, ");" TO g_CFILE
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Putbyte(STRING arg$)
LOCAL dim
LOCAL var$, to$, size$
' Check if FROM is available
IF NOT(INSTR(arg$, " TO ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing TO in PUTBYTE statement at line at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the variablename, filedescriptor
var$ = LEFT$(arg$, INSTRREV(arg$, " TO "))
to$ = CHOP$(MID$(arg$, INSTRREV(arg$, " TO ") + 4))
' Check if SIZE is available
IF INSTR(to$, " SIZE ") THEN
size$ = MID$(to$, INSTR(to$, " SIZE ") + 6)
to$ = MID$(to$, 1, INSTR(to$, " SIZE "))
ELSE
size$ = "1"
END IF
' Translate function to C function
WRITELN "if(!__b2c__trap){if(__b2c__memory__check((char *)", var$, ")) {ERROR=1; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
WRITELN "__b2c__counter = fwrite((char*)", var$, ", sizeof(", g_OPTION_MEMTYPE$, "), ", size$, ", ", to$, ");" TO g_CFILE
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Getfile(STRING arg$)
LOCAL dim, check
' Check if FROM is available
IF NOT(INSTR(arg$, " FROM ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing FROM in GETFILE statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the variablename, filedescriptor
SPLIT arg$ BY " " TO element$ SIZE dim
' Translate function to C function
WRITELN "__b2c__dir = readdir(", element$[3], ");" TO g_CFILE
' Check if variable is declared
IF NOT(INSTR(element$[1], "[")) AND NOT(INSTR(element$[1], "]")) THEN
check = Search(g_HFILE$, CONCAT$("char *", element$[1], " = NULL;"), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
check = Search(g_CFILE$, CONCAT$("char *", element$[1], " = NULL;"), 0)
ENDIF
END IF
IF check < 0 AND NOT(REGEX(element$[1], "\\[.*\\]")) AND NOT(INSTR(element$[1], ".")) THEN WRITELN "char *", element$[1], " = NULL;" TO g_HFILE
' Always realloc VAR to correct size, maybe it was resized somewhere else
WRITELN "if(__b2c__dir != NULL) {", element$[1], " = realloc(", element$[1], ", (strlen(__b2c__dir->d_name)+1)*sizeof(char));" TO g_CFILE
' Make sure internal var is copied to var of program
WRITELN "strcpy(", element$[1], ", __b2c__dir->d_name); ", element$[1], "[strlen(__b2c__dir->d_name)] = '\\0';}" TO g_CFILE
WRITELN "else {", element$[1], " = realloc(", element$[1], ", sizeof(char)); ", element$[1], "[0] = '\\0';}" TO g_CFILE
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Receive(STRING arg$)
LOCAL dim, check
LOCAL size$, chunk$
' Check if FROM is available
IF NOT(INSTR(arg$, " FROM ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: Missing FROM in RECEIVE statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get filedescriptor
SPLIT CHOP$(arg$) BY " " TO element$ SIZE dim
' Check for optional chunksize
SELECT dim
CASE 5
chunk$ = element$[5]
size$ = ""
CASE 7
chunk$ = element$[5]
size$ = element$[7]
DEFAULT
chunk$ = STR$(g_BUFFER_SIZE)
size$ = ""
END SELECT
' Variable may not be array, these should be defined with DECLARE
IF LEN(size$) > 0 AND NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) THEN
check = Check_Declared(g_HFILE$, size$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, size$, 0)
IF ISFALSE(check) THEN WRITELN "long ", size$, ";" TO g_HFILE
END IF
' Check if variable is declared
IF INSTR(element$[1], g_STRINGSIGN$) THEN
check = Search(g_HFILE$, CONCAT$("char *", element$[1], " = NULL;"), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
check = Search(g_CFILE$, CONCAT$("char *", element$[1], " = NULL;"), 0)
ENDIF
IF check < 0 THEN WRITELN "char *", element$[1], " = NULL;" TO g_HFILE
WRITELN element$[1], " = (char*)realloc(", element$[1], ", (", chunk$, "+1)*sizeof(char)); memset(", element$[1], ", '\\0', sizeof(char)*(", chunk$, "+1));" TO g_CFILE
END IF
' Translate function to C function
IF LEN(size$) EQ 0 THEN
WRITELN "if(recv(", element$[3], ", (void*)", element$[1], ", ", chunk$, ", 0) < 0) {if(!__b2c__trap){ERROR = 14;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
ELSE
WRITELN "if((", size$, " = recv(", element$[3], ", (void*)", element$[1], ", ", chunk$,", 0)) < 0) {if(!__b2c__trap){ERROR = 14;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
END IF
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Send(STRING arg$)
LOCAL to$, var$, chunk$
' Check if TO is available
IF NOT(INSTR(arg$, " TO ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: Missing TO in SEND statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the variablename without surrounding spaces
var$ = LEFT$(arg$, INSTR(arg$, " TO "))
' Get filedescriptor
to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4))
IF INSTR(to$, " CHUNK ") THEN
chunk$ = MID$(to$, INSTR(to$, " CHUNK ") + 7)
to$ = MID$(to$, 1, INSTR(to$, " CHUNK ") - 1)
ELSE
chunk$ = CONCAT$("strlen(", var$, ")")
END IF
' Translate function to C function
WRITELN "if(send(", to$, ", (void*)", var$, ", ", chunk$, ", 0) < 0) {if(!__b2c__trap){ERROR = 15; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Getline(STRING arg$)
LOCAL dim, check
' Check if FROM is available
IF NOT(INSTR(arg$, " FROM ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing FROM in GETLINE statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: variable for GETLINE at line $g_COUNTER in file ", STR$(g_COUNTER), " in file '", g_CURFILE$, "' must be string!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check if variable is declared
IF NOT(INSTR(element$[1], "[")) AND NOT(INSTR(element$[1], "]")) THEN
' Is variable declared already?
check = Search(g_HFILE$, CONCAT$("char *", element$[1], " = NULL;"), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
check = Search(g_CFILE$, CONCAT$("char *", element$[1], " = NULL;"), 0)
ENDIF
IF check < 0 THEN WRITELN "char *", element$[1], " = NULL;" TO g_HFILE
END IF
' Translate function to C function
WRITELN "if (", element$[3], " == NULL ||", CONCAT$("*", element$[3]) , " == '\\0') {", element$[1], " = (char*)realloc(", element$[1], ", 2*sizeof(char)); strcpy(", element$[1], ", \"\");}" TO g_CFILE
WRITELN "else { __b2c__assign = ", element$[3], "; while(*", element$[3], " != '\\0' && *", element$[3], " != '\\n') ", element$[3], "++;" TO g_CFILE
' Make sure internal var is copied to var of program
WRITELN element$[1], " = (char*)realloc(", element$[1], ", (", element$[3], "-__b2c__assign+1)*sizeof(char));" TO g_CFILE
WRITELN "strncpy(", element$[1], ", __b2c__assign, ", element$[3], "-__b2c__assign);" TO g_CFILE
' Make sure to end the string
WRITELN element$[1], "[(", element$[3], "-__b2c__assign)] = '\\0'; ", element$[3], "++;}" TO g_CFILE
LABEL End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing TO in PUTLINE statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the variablename, filedescriptor
var$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TO ")))
to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4))
' Start miniparser
in_string = FALSE
in_func = 0
pos = 1
escaped = 0
FOR x = 1 TO LEN(var$)
IF ISTRUE(EQUAL(MID$(var$, x, 1), ",")) THEN
IF ISFALSE(in_string) AND ISFALSE(in_func) THEN
len = INSTR(MID$(var$, pos, x-pos), "(")-1
IF len < 0 THEN len = x-pos
IF INSTR(MID$(var$, pos, len), g_STRINGSIGN$) OR INSTR(MID$(var$, pos, len), CHR$(34)) THEN
WRITELN "strcat(", to$, ", ", CHOP$(MID$(var$, pos, x-pos)), ");", to$, "+=strlen(", CHOP$(MID$(var$, pos, x-pos)), ");" TO g_CFILE
ELSE
WRITELN "strcat(", to$, ", STR", g_STRINGSIGN$, "(", CHOP$(MID$(var$, pos, x-pos)), "));", to$, "+=strlen(STR", g_STRINGSIGN$, "(", CHOP$(MID$(var$, pos, x-pos)), "));" TO g_CFILE
END IF
pos = x+1
escaped = FALSE
END IF
ELIF EQUAL(MID$(var$, x, 1), "\\") THEN
escaped = TRUE
ELIF ISTRUE(EQUAL(MID$(var$, x, 1), CHR$(34))) THEN
IF ISFALSE(escaped) THEN
in_string = NOT(in_string)
END IF
escaped = FALSE
ELIF ISTRUE(EQUAL(MID$(var$, x, 1), "(")) THEN
IF ISFALSE(in_string) THEN
INCR in_func
END IF
escaped = FALSE
ELIF ISTRUE(EQUAL(MID$(var$, x, 1), ")")) THEN
IF ISFALSE(in_string) THEN
DECR in_func
END IF
escaped = FALSE
ELSE
escaped = FALSE
ENDIF
NEXT
var$ = MID$(var$, pos)
' Check if var is string var
len = INSTR(MID$(var$, pos, x-pos), "(")-1
IF len < 0 THEN len = x-pos
IF INSTR(LEFT$(var$, len), g_STRINGSIGN$) OR INSTR(LEFT$(var$, len), CHR$(34)) THEN
WRITELN "strcat(", to$, ", ", var$, "); strcat(", to$, ", \"\\n\"); ", to$, "+=strlen(", var$, ")+1;" TO g_CFILE
ELSE
WRITELN "strcat(", to$, ", STR", g_STRINGSIGN$, "(", var$, ")); strcat(", to$, ", \"\\n\"); ", to$, "+=strlen(STR", g_STRINGSIGN$, "(", var$, "))+1;" TO g_CFILE
END IF
LABEL End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty SUB/FUNCTION at at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check if we are in a sub already
IF LEN(g_FUNCNAME$) > 0 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: cannot define a SUB/FUNCTION within a SUB/FUNCTION at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the funcname
IF INSTR(arg$, "(") THEN
g_ORIGFUNCNAME$ = CHOP$(LEFT$(arg$, INSTR(arg$, "(")))
g_PROTOTYPE$ = CHOP$(LEFT$(arg$, INSTR(arg$, "(")))
ELSE
g_ORIGFUNCNAME$ = CHOP$(CONCAT$(arg$, "("))
g_PROTOTYPE$ = CHOP$(CONCAT$(arg$, "("))
END IF
' Start miniparser to duplicate string arguments
arg_s$ = CHOP$(MID$(arg$, INSTR(arg$, "(") + 1))
SPLIT arg_s$ BY "," TO element$ SIZE dim
x = 1
WHILE dim > 1 DO
IF INSTR(element$[x], "STRING ") OR INSTR(element$[x], "char* ") THEN
element$[x] = CHOP$(element$[x])
arr$ = MID$(element$[x], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ")-1)
dim$ = MID$(element$[x], INSTR(element$[x], "[")+1, INSTR(element$[x], "]") - INSTR(element$[x], "[")-1)
IF NOT(INSTR(element$[x], g_STRINGSIGN$)) AND REGEX(element$[x], ".*\\[.*\\].*") THEN
g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"],")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, " char** ", arr$, " = __b2c_", arr$, ";")
g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ",")
ELIF NOT(INSTR(element$[x], g_STRINGSIGN$)) THEN
g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ",")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), " = __b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ";")
g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ",")
ELIF REGEX(element$[x], ".*\\[.*\\].*") THEN
IF LEN(dim$) < 1 THEN
g_ORIGFUNCNAME$ = CHOP$(CONCAT$(g_ORIGFUNCNAME$, " ", element$[x], ","))
g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ",")
ELSE
g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"],")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"] = { NULL };")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++){if(__b2c_", arr$, "[__b2c__ctr]!=NULL) ", arr$, "[__b2c__ctr] = strdup(__b2c_", arr$, "[__b2c__ctr]);}")
g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++)if(", arr$, "[__b2c__ctr]!=NULL){free(", arr$, "[__b2c__ctr]);}")
g_PROTOTYPE$=CONCAT$(g_PROTOTYPE$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ",")
END IF
ELSE
g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ",")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), " = strdup(__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ");")
g_LOCALSTRINGS$ = CONCAT$(g_LOCALSTRINGS$, " ", CHOP$(MID$(element$[x], INSTR(element$[x], " "))))
g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ",")
END IF
ELSE
element$[x] = CHOP$(element$[x])
IF REGEX(element$[x], ".*\\[.*\\].*\\].*") THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: cannot pass multidimensional numeric array at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELIF REGEX(element$[x], ".*\\[\\].*") THEN
g_ORIGFUNCNAME$ = CHOP$(CONCAT$(g_ORIGFUNCNAME$, " ", element$[x], ","))
ELIF REGEX(element$[x], ".*\\[.*\\].*") THEN
dim$ = MID$(element$[x], INSTR(element$[x], "[")+1, INSTR(element$[x], "]") - INSTR(element$[x], "[")-1)
arr$ = MID$(element$[x], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ") - 1)
g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, MID$(element$[x], 1, INSTR(element$[x], " "))," __b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"],")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, MID$(element$[x], 1, INSTR(element$[x], " ")), " ", arr$, "[", dim$, "+", STR$(g_OPTION_BASE), "] = { 0 };")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++){", arr$, "[__b2c__ctr] = __b2c_", arr$, "[__b2c__ctr];}")
ELIF INSTR(element$[x], "VAR ") THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: variable argument list cannot be followed by other arguments at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
g_ORIGFUNCNAME$ = CHOP$(CONCAT$(g_ORIGFUNCNAME$, " ", element$[x], ","))
END IF
g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", CHOP$(element$[x]), ",")
END IF
INCR x
DECR dim
WEND
' Last token in the sequence of arguments
IF ISTRUE(dim) THEN
element$[x] = CHOP$(LEFT$(element$[x], INSTR(element$[x], ")") - 1))
IF INSTR(element$[x], "STRING ") OR INSTR(element$[x], "char* ") THEN
arr$ = MID$(element$[x], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ")-1)
dim$ = MID$(element$[x], INSTR(element$[x], "[")+1, INSTR(element$[x], "]") - INSTR(element$[x], "[")-1)
IF NOT(INSTR(element$[x], g_STRINGSIGN$)) AND REGEX(element$[x], ".*\\[.*\\].*") THEN
g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"])")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, " char** ", arr$, " = __b2c_", arr$, ";")
g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ")")
ELIF NOT(INSTR(element$[x], g_STRINGSIGN$)) THEN
g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ")")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), " = __b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ";")
g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ")")
ELIF REGEX(element$[x], ".*\\[.*\\].*") THEN
IF LEN(dim$) < 1 THEN
g_ORIGFUNCNAME$ = CHOP$(CONCAT$(g_ORIGFUNCNAME$, " ", element$[x], ")"))
g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ")")
ELSE
g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"])")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"] = { NULL };")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++){if(__b2c_", arr$, "[__b2c__ctr]!=NULL) ", arr$, "[__b2c__ctr] = strdup(__b2c_", arr$, "[__b2c__ctr]);}")
g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++)if(", arr$, "[__b2c__ctr]!=NULL){free(", arr$, "[__b2c__ctr]);}")
g_PROTOTYPE$=CONCAT$(g_PROTOTYPE$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ")")
END IF
ELSE
g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ")")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "char *", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), " = strdup(__b2c_", CHOP$(MID$(element$[x], INSTR(element$[x], " "))), ");")
g_LOCALSTRINGS$ = CONCAT$(g_LOCALSTRINGS$, " ", CHOP$(MID$(element$[x], INSTR(element$[x], " "))))
g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ")")
END IF
ELSE
IF INSTR(g_ORIGFUNCNAME$, element$[x]) OR LEN(element$[x]) EQ 0 THEN element$[x] = "void "
IF REGEX(element$[x], ".*\\[.*\\].*\\].*") THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: cannot pass multidimensional numeric array at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELIF REGEX(element$[x], ".*\\[\\].*") THEN
g_ORIGFUNCNAME$ = CHOP$(CONCAT$(g_ORIGFUNCNAME$, " ", element$[x], ")"))
ELIF REGEX(element$[x], ".*\\[.*\\].*") THEN
dim$ = MID$(element$[x], INSTR(element$[x], "[")+1, INSTR(element$[x], "]") - INSTR(element$[x], "[")-1)
arr$ = MID$(element$[x], INSTR(element$[x], " ")+1, INSTR(element$[x], "[") - INSTR(element$[x], " ") - 1)
g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, MID$(element$[x], 1, INSTR(element$[x], " "))," __b2c_", arr$, "[", dim$, "+", STR$(g_OPTION_BASE),"])")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, MID$(element$[x], 1, INSTR(element$[x], " ")), " ", arr$, "[", dim$, "+", STR$(g_OPTION_BASE), "] = { 0 };")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "for(__b2c__ctr=0; __b2c__ctr<", dim$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++){", arr$, "[__b2c__ctr] = __b2c_", arr$, "[__b2c__ctr];}")
ELIF INSTR(element$[x], "VAR ") THEN
IF INSTR(g_PROTOTYPE$, ",") THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: variable argument list cannot be preceded by other arguments at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
IF NOT(INSTR(element$[x], " SIZE ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: variable argument list lacks SIZE argument at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: variable argument list is not string at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
check = Check_Declared(g_HFILE$, size$, g_HEADER_SEARCHPOS)
IF ISFALSE(check) THEN g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, " long ", size$, ";")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "long __b2c__var_", arr$, " = ", STR$(g_OPTION_BASE), "; va_list __b2c__ap; char **", arr$, " = NULL; char* __b2c__va = NULL; ", arr$, " = (char **)realloc(", arr$, ", (__b2c__var_", arr$, "+1) * sizeof(char*));")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "va_start(__b2c__ap, __b2c__name); if(__b2c__name != NULL)", arr$, "[__b2c__var_", arr$, "] = 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$ = CONCAT$(g_STRINGARGS$, "__b2c__va = va_arg(__b2c__ap, char*); if(__b2c__va != NULL) ", arr$, "[__b2c__var_", arr$, "] = strdup(__b2c__va); else ", arr$, "[__b2c__var_", arr$, "] = NULL; }")
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, "va_end(__b2c__ap); ", size$, " = __b2c__var_", arr$, " - ", STR$(g_OPTION_BASE), "; if(__b2c__var_", arr$, " > 0) __b2c__var_", arr$, "--;")
g_PROTOTYPE$ = CONCAT$("__", g_PROTOTYPE$)
g_ORIGFUNCNAME$ = CONCAT$(g_ORIGFUNCNAME$, "char *__b2c__name, ...)")
element$[x] = "char*, ..."
g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, "if(", arr$, " != NULL) {for(__b2c__ctr=", STR$(g_OPTION_BASE), "; __b2c__ctr<=__b2c__var_", arr$, "; __b2c__ctr++) if(", arr$, "[__b2c__ctr]!=NULL){free(", arr$, "[__b2c__ctr]);} free(", arr$, ");}")
ELSE
g_ORIGFUNCNAME$ = CHOP$(CONCAT$(g_ORIGFUNCNAME$, " ", element$[x], ")"))
END IF
g_PROTOTYPE$ = CONCAT$(g_PROTOTYPE$, " ", element$[x], ")")
END IF
END IF
' Get original function name
IF INSTR(g_ORIGFUNCNAME$, " (") THEN
g_FUNCNAME$ = LEFT$(g_ORIGFUNCNAME$, INSTR(g_ORIGFUNCNAME$, " (") - 1)
ELIF INSTR(g_ORIGFUNCNAME$, "(") THEN
g_FUNCNAME$ = LEFT$(g_ORIGFUNCNAME$, INSTR(g_ORIGFUNCNAME$, "(") - 1)
ELSE
g_FUNCNAME$ = g_ORIGFUNCNAME$
END IF
' Close the current C file
CLOSE FILE g_CFILE
' Add macro in case of VAR argument
IF INSTR(element$[x], " ...") THEN
WRITELN "#define ", g_FUNCNAME$, "(...) __", g_FUNCNAME$, "(__VA_ARGS__, NULL)" TO g_HFILE
g_ORIGFUNCNAME$ = CONCAT$("__", g_ORIGFUNCNAME$)
END IF
' Make symbol known to parser
g_IMPORTED$ = CONCAT$(g_FUNCNAME$, " ", g_IMPORTED$)
' Switch to header file
g_COPY_CFILE$ = g_CFILE$
g_CFILE$ = CONCAT$(LEFT$(g_CFILE$, INSTR(g_CFILE$, ".c")), g_FUNCNAME$, ".tmp")
' Save CATCH routine
g_ORIGCATCHGOTO$ = g_CATCHGOTO$
g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT"
' Open temp C file
OPEN g_CFILE$ FOR WRITING AS g_CFILE
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Endsub()
LOCAL tmp_HFILE TYPE FILE*
LOCAL line$
LOCAL dim, x
' Close the current C file
CLOSE FILE g_CFILE
' Put prototype to header file
WRITELN "void ", g_PROTOTYPE$, "; /* noparse */" TO g_HFILE
g_PROTOTYPE$ = ""
' Open temporary header file
OPEN CONCAT$(g_TEMPDIR$, "/", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h") FOR WRITING AS tmp_HFILE
' Get original function name
WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO tmp_HFILE
WRITELN "/* noparse ", g_CURFILE$, " BACON LINE ", g_COUNTER, " */" TO tmp_HFILE
IF INSTR(g_ORIGFUNCNAME$, " (") THEN
WRITELN "void ", g_ORIGFUNCNAME$, " {" TO tmp_HFILE
ELIF INSTR(g_ORIGFUNCNAME$, "(") THEN
WRITELN "void ", g_ORIGFUNCNAME$, " {" TO tmp_HFILE
ELSE
WRITELN "void ", g_FUNCNAME$, "(void) {" TO tmp_HFILE
END IF
' Finalize sub
WRITELN g_STRINGARGS$ TO tmp_HFILE
OPEN g_CFILE$ FOR READING AS g_CFILE
WHILE NOT(ENDFILE(g_CFILE)) DO
READLN line$ FROM g_CFILE
IF NOT(ENDFILE(g_CFILE)) THEN WRITELN line$ TO tmp_HFILE
WEND
CLOSE FILE g_CFILE
' Free strings variables if there are any
WRITELN g_STRINGARRAYS$ TO tmp_HFILE
SPLIT g_LOCALSTRINGS$ BY " " TO element$ SIZE dim
FOR x = 1 TO dim
IF LEN(element$[x]) > 0 THEN WRITELN "if(", element$[x], " != NULL) free(", element$[x], ");" TO tmp_HFILE
NEXT
WRITELN "__B2C__PROGRAM__EXIT: ;" TO tmp_HFILE
WRITELN "}" TO tmp_HFILE
CLOSE FILE tmp_HFILE
' Include header file
IF NOT(INSTR(g_INCLUDE_FILES$, CONCAT$(LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h"))) THEN
g_INCLUDE_FILES$ = CONCAT$(g_INCLUDE_FILES$, " ", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h")
END IF
' Add to total filelist
g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_TEMPDIR$, "/", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h")
' Delete temp funcfile
DELETE FILE g_CFILE$
' Restore mainfile
g_CFILE$ = g_COPY_CFILE$
OPEN g_CFILE$ FOR APPENDING AS g_CFILE
' Restore CATCH routine
g_CATCHGOTO$ = g_ORIGCATCHGOTO$
' Reset variables
g_ORIGFUNCNAME$ = ""
g_FUNCNAME$ = ""
g_LOCALSTRINGS$ = ""
g_STRINGARRAYS$ = ""
g_STRINGARGS$ = ""
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Endfunction()
IF ISFALSE(LEN(g_FUNCTYPE$)) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: function '", g_FUNCNAME$, "' was defined without returning a value or string!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Close the current C file
CLOSE FILE g_CFILE
' Put prototype to header file
WRITELN g_FUNCTYPE$, " ", g_PROTOTYPE$, "; /* noparse */" TO g_HFILE
g_PROTOTYPE$ = ""
' Open temporary header file
OPEN CONCAT$(g_TEMPDIR$, "/", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h") FOR WRITING AS tmp_HFILE
' Get original function name
WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO tmp_HFILE
WRITELN "/* noparse ", g_CURFILE$, " BACON LINE ", g_COUNTER, " */" TO tmp_HFILE
IF NOT(INSTR(g_ORIGFUNCNAME$, "(")) THEN
WRITELN g_FUNCTYPE$, " ", g_FUNCNAME$, "(void) {" TO tmp_HFILE
ELSE
WRITELN g_FUNCTYPE$, " ", g_ORIGFUNCNAME$, " {" TO tmp_HFILE
END IF
' Add function body
WRITELN g_STRINGARGS$ TO tmp_HFILE
OPEN g_CFILE$ FOR READING AS g_CFILE
WHILE NOT(ENDFILE(g_CFILE)) DO
READLN line$ FROM g_CFILE
IF NOT(ENDFILE(g_CFILE)) THEN WRITELN line$ TO tmp_HFILE
WEND
CLOSE FILE g_CFILE
WRITELN "__B2C__PROGRAM__EXIT: ;" TO tmp_HFILE
' Make sure the function always returns something
IF INSTR(g_FUNCTYPE$, "char*") THEN WRITELN "return (\"\");}" TO tmp_HFILE
ELSE WRITELN "return (0);}" TO tmp_HFILE
CLOSE FILE tmp_HFILE
' Include header file
IF NOT(INSTR(g_INCLUDE_FILES$, CONCAT$(LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h"))) THEN
g_INCLUDE_FILES$ = CONCAT$(g_INCLUDE_FILES$, " ", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h")
END IF
' Add to total filelist
g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_TEMPDIR$, "/", LEFT$(g_CURFILE$, INSTR(g_CURFILE$, ".bac")), g_FUNCNAME$, ".h")
' Delete temp funcfile
DELETE FILE g_CFILE$
' Restore mainfile
g_CFILE$ = g_COPY_CFILE$
OPEN g_CFILE$ FOR APPENDING AS g_CFILE
' Restore CATCH routine
g_CATCHGOTO$ = g_ORIGCATCHGOTO$
' Clear function variables
g_ORIGFUNCNAME$ = ""
g_FUNCNAME$ = ""
g_FUNCTYPE$ = ""
g_LOCALSTRINGS$ = ""
g_STRINGARRAYS$ = ""
g_STRINGARGS$ = ""
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Return(STRING arg$)
LOCAL type$, thearg$
LOCAL dim, x
' 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$, 0)
' 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*)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*)realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], 2*sizeof(char));" TO g_CFILE
WRITELN "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], \"\");}" TO g_CFILE
thearg$ = CONCAT$(MID$(arg$, 1, INSTR(arg$, "(")), "__b2c__rbuffer[__b2c__rbuffer_ptr]", MID$(arg$, INSTRREV(arg$, ")")) )
' Check type of var, string or normal string?
ELIF INSTR(arg$, g_STRINGSIGN$) OR INSTR(arg$, CHR$(34)) OR INSTR(g_FUNCNAME$, g_STRINGSIGN$) THEN
g_FUNCTYPE$ = "char* "
WRITELN "__b2c__rbuffer_ptr++; if(__b2c__rbuffer_ptr >= ", g_MAX_RBUFFERS, ") __b2c__rbuffer_ptr=0; if(", arg$, " != NULL)" TO g_CFILE
WRITELN " {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], (strlen(", arg$, ")+1)*sizeof(char));" TO g_CFILE
WRITELN "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], ", arg$, ");}" TO g_CFILE
WRITELN "else {__b2c__rbuffer[__b2c__rbuffer_ptr] = (char*)realloc(__b2c__rbuffer[__b2c__rbuffer_ptr], 2*sizeof(char));" TO g_CFILE
WRITELN "strcpy(__b2c__rbuffer[__b2c__rbuffer_ptr], \"\");}" TO g_CFILE
thearg$ = "__b2c__rbuffer[__b2c__rbuffer_ptr]"
' Check if float
ELIF INSTR(arg$, ".") THEN
g_FUNCTYPE$ = "double "
thearg$ = arg$
' Check if no alpha chars (then integer value)
ELIF REGEX(arg$, "[0-9]") THEN
g_FUNCTYPE$ = "long "
thearg$ = arg$
' Assume variable, check if declared before
ELIF ISTRUE(LEN(type$)) THEN
IF INSTR(type$, "DIR* ") THEN
g_FUNCTYPE$ = "DIR* "
ELIF INSTR(type$, "FILE ") THEN
g_FUNCTYPE$ = "FILE* "
ELIF INSTR(type$, "int* ") THEN
g_FUNCTYPE$ = "int* "
ELIF INSTR(type$, "float* ") THEN
g_FUNCTYPE$ = "float* "
ELIF INSTR(type$, "double* ") THEN
g_FUNCTYPE$ = "double* "
ELIF INSTR(type$, "char* ") OR INSTR(type$, "STRING ") THEN
g_FUNCTYPE$ = "char* "
ELIF INSTR(type$, "long* ") THEN
g_FUNCTYPE$ = "long* "
ELIF INSTR(type$, "void* ") THEN
g_FUNCTYPE$ = "void* "
ELIF INSTR(type$, "int ") THEN
g_FUNCTYPE$ = "int "
ELIF INSTR(type$, "float ") THEN
g_FUNCTYPE$ = "float "
ELIF INSTR(type$, "double ") OR INSTR(type$, "FLOATING ") THEN
g_FUNCTYPE$ = "double "
ELIF INSTR(type$, "char ") THEN
g_FUNCTYPE$ = "char "
ELIF INSTR(type$, "long ") OR INSTR(type$, "NUMBER ") THEN
g_FUNCTYPE$ = "long "
ELIF INSTR(type$, "void ") THEN
g_FUNCTYPE$ = "void "
END IF
thearg$ = arg$
' Not declared, assume integer variable
ELSE
g_FUNCTYPE$ = "long "
thearg$ = arg$
END IF
' Free strings variables if there are any
WRITELN g_STRINGARRAYS$ TO g_CFILE
SPLIT g_LOCALSTRINGS$ BY " " TO element$ SIZE dim
FOR x = 1 TO dim
IF LEN(element$[x]) > 0 THEN WRITELN "if(", element$[x], " != NULL) free(", element$[x], ");" TO g_CFILE
NEXT
' The actual return value
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty DEF FN at at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Translate to C macro
sym$ = CHOP$(MID$(arg$, INSTR(arg$, " ")))
WRITELN "#define ", LEFT$(sym$, INSTR(sym$, "=") -1), " (", MID$(sym$, INSTR(sym$, "=") + 1), ")" TO g_HFILE
' Make symbol known to parser
g_IMPORTED$ = CONCAT$(LEFT$(sym$, INSTR(sym$, "(") - 1), " ", g_IMPORTED$)
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Const(STRING arg$)
' Check if we have an argument at all
IF ISFALSE(LEN(arg$)) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty CONST at at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
WRITELN "#define ", LEFT$(arg$, INSTR(arg$, "=") - 1), " (", CHOP$(MID$(arg$, INSTR(arg$, "=") + 1)), ")" TO g_HFILE
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Push(STRING arg$)
LOCAL type$
' Check if we have an argument at all
IF ISFALSE(LEN(CHOP$(arg$))) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty PUSH at at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
IF NOT(INSTR(arg$, ".")) THEN
type$ = Check_Type$(g_HFILE$, arg$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN
type$ = Check_Type$(g_CFILE$, arg$, 0)
END IF
END IF
' Allocate space for type
WRITELN "__b2c__typestack = (int*)realloc(__b2c__typestack, (__b2c__stackptr+1)*sizeof(int));" TO g_CFILE
' Check type of var, string?
IF INSTR(arg$, g_STRINGSIGN$) THEN
WRITELN "__b2c__stringstack = (char**)realloc(__b2c__stringstack, (__b2c__stackptr+1)*sizeof(char*));" TO g_CFILE
WRITELN "if(__b2c__stackptr == 0){ __b2c__stringstack[__b2c__stackptr] = realloc(__b2c__stringstack[__b2c__stackptr], (strlen(", arg$, ")+1)*sizeof(char));" TO g_CFILE
WRITELN "strcpy(__b2c__stringstack[__b2c__stackptr], ", arg$, ");} else __b2c__stringstack[__b2c__stackptr] = strdup(", arg$, ");" TO g_CFILE
WRITELN "__b2c__typestack[__b2c__stackptr] = 1;" TO g_CFILE
' Check if it is a normal string
ELIF INSTR(arg$, CHR$(34)) THEN
WRITELN "__b2c__stringstack = (char**)realloc(__b2c__stringstack, (__b2c__stackptr+1)*sizeof(char*));" TO g_CFILE
WRITELN "if(__b2c__stackptr == 0){ __b2c__stringstack[__b2c__stackptr] = realloc(__b2c__stringstack[__b2c__stackptr], (strlen(", arg$, ")+1)*sizeof(char));" TO g_CFILE
WRITELN "strcpy(__b2c__stringstack[__b2c__stackptr], ", arg$, ");} else __b2c__stringstack[__b2c__stackptr] = strdup(", arg$, ");" TO g_CFILE
WRITELN "__b2c__typestack[__b2c__stackptr] = 1;" TO g_CFILE
' Check if float
ELIF INSTR(arg$, ".") THEN
WRITELN "__b2c__doublestack = (double*)realloc(__b2c__doublestack, (__b2c__stackptr+1)*sizeof(double));" TO g_CFILE
WRITELN "__b2c__doublestack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE
WRITELN "__b2c__typestack[__b2c__stackptr] = 2;" TO g_CFILE
' Check if no alpha chars (then integer value)
ELIF NOT(REGEX(arg$, "[a-zA-Z]")) THEN
WRITELN "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" TO g_CFILE
WRITELN "__b2c__longstack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE
WRITELN "__b2c__typestack[__b2c__stackptr] = 3;" TO g_CFILE
' Assume variable, check if declared before
ELIF ISTRUE(LEN(type$)) THEN
IF REGEX(type$, "double .*") THEN
WRITELN "__b2c__doublestack = (double*)realloc(__b2c__doublestack, (__b2c__stackptr+1)*sizeof(double));" TO g_CFILE
WRITELN "__b2c__doublestack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE
WRITELN "__b2c__typestack[__b2c__stackptr] = 2;" TO g_CFILE
ELSE
WRITELN "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" TO g_CFILE
WRITELN "__b2c__longstack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE
WRITELN "__b2c__typestack[__b2c__stackptr] = 3;" TO g_CFILE
END IF
' Not declared, assume integer variable
ELSE
WRITELN "__b2c__longstack = (long*)realloc(__b2c__longstack, (__b2c__stackptr+1)*sizeof(long));" TO g_CFILE
WRITELN "__b2c__longstack[__b2c__stackptr] = ", arg$, ";" TO g_CFILE
WRITELN "__b2c__typestack[__b2c__stackptr] = 3;" TO g_CFILE
END IF
' Increase stackpointer
WRITELN "__b2c__stackptr++;" TO g_CFILE
LABEL End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty PULL at at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Argument must be a variable
IF NOT(REGEX(arg$, "[a-zA-Z]+.*")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: argument in PULL statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "' is not a variable!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Decrease stackpointer again
WRITELN "__b2c__stackptr--;" TO g_CFILE
WRITELN "if(__b2c__stackptr < 0) __b2c__stackptr=0;" TO g_CFILE
' Get the last value from stack
IF INSTR(arg$, g_STRINGSIGN$) THEN
check = Search(g_HFILE$, CONCAT$("char *", arg$, " = NULL;"), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
check = Search(g_CFILE$, CONCAT$("char *", arg$, " = NULL;"), 0)
ENDIF
IF check < 0 THEN WRITELN "char *", arg$, " = NULL;" TO g_HFILE
WRITELN "if(__b2c__typestack[__b2c__stackptr] == 1) {" TO g_CFILE
WRITELN arg$, " = (char*)realloc(", arg$, ", (strlen(__b2c__stringstack[__b2c__stackptr])+1)*sizeof(char));" TO g_CFILE
WRITELN "strcpy(", arg$, ", __b2c__stringstack[__b2c__stackptr]); if(__b2c__stackptr > 0) free(__b2c__stringstack[__b2c__stackptr]);}" TO g_CFILE
ELSE
' Variable may not be array, these should be defined with DECLARE
IF NOT(REGEX(arg$, "\\[.*\\]")) AND NOT(INSTR(arg$, ".")) THEN
' Not declared? Assume long
check = Check_Declared(g_HFILE$, arg$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, arg$, 0)
IF ISFALSE(check) THEN WRITELN "long ", arg$, "; /* pull */" TO g_HFILE
END IF
' See how var was declared
type$ = Check_Type$(g_HFILE$, arg$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN
type$ = Check_Type$(g_CFILE$, arg$, 0)
END IF
' Make sure internal var is copied to var of program
IF INSTR(type$, "double ") OR INSTR(type$, "float ") OR INSTR(type$, "FLOATING ") THEN
WRITELN "if(__b2c__typestack[__b2c__stackptr] == 2) ", arg$, "=__b2c__doublestack[__b2c__stackptr];" TO g_CFILE
ELIF INSTR(type$, "long ") OR INSTR(type$, "int ") OR INSTR(type$, "NUMBER ") THEN
WRITELN "if(__b2c__typestack[__b2c__stackptr] == 3) ", arg$, "=__b2c__longstack[__b2c__stackptr];" TO g_CFILE
ELSE
WRITELN "if(__b2c__typestack[__b2c__stackptr] == 1) {" TO g_CFILE
WRITELN arg$, " = (char*)realloc(", arg$, ", (strlen(__b2c__stringstack[__b2c__stackptr])+1)*sizeof(char));" TO g_CFILE
WRITELN "strcpy(", arg$, ", __b2c__stringstack[__b2c__stackptr]); if(__b2c__stackptr > 0) free(__b2c__stringstack[__b2c__stackptr]);}" TO g_CFILE
END IF
END IF
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Import(STRING arg$)
LOCAL lib$, type$, sym$, tmp$, token$, alias$
LOCAL check
' Check if FROM is available
IF NOT(INSTR(arg$, " FROM ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing FROM in IMPORT statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the symbolname without surrounding spaces and doublequotes
IF INSTR(arg$, "(") THEN
sym$ = REPLACE$((CHOP$(LEFT$(arg$, INSTR(arg$, "(") - 1))), CHR$(34), "")
tmp$ = CHOP$(MID$(arg$, INSTR(arg$, " FROM ") + 6))
token$ = CHOP$(MID$(arg$, 1, INSTRREV(arg$, ")") - 1))
ELSE
sym$ = REPLACE$((CHOP$(MID$(arg$, 1, INSTR(arg$, " FROM ") - 1))), CHR$(34), "")
tmp$ = CHOP$(MID$(arg$, INSTR(arg$, " FROM ") + 6))
token$ = ""
END IF
' Check if TYPE is available
IF NOT(INSTR(arg$, " TYPE ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing TYPE in IMPORT statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get library and type
lib$ = CHOP$(MID$(tmp$, 1, INSTR(tmp$, " TYPE ")))
type$ = CHOP$(MID$(tmp$, INSTR(tmp$, " TYPE ") + 6))
' Check if ALIAS is there
IF INSTR(type$, " ALIAS ") THEN
alias$ = REPLACE$(MID$(type$, INSTR(type$, " ALIAS ") + 7), CHR$(34), "")
WRITELN "#define ", alias$, " ", sym$ TO g_HFILE
g_IMPORTED$ = CONCAT$(alias$, " ", g_IMPORTED$)
type$ = LEFT$(type$, INSTR(type$, " ALIAS ") - 1)
ENDIF
ptr$ = REPLACE$(REPLACE$(lib$, CHR$(34), ""), "-", "")
ptr$ = REPLACE$(REPLACE$(REPLACE$(ptr$, ".", ""), "/", ""), "_", "")
' If library is libm or libc, skip dlopen as we're linking with those anyway
IF NOT(INSTR(lib$, "libc.so") ) AND NOT(INSTR(lib$, "libm.so")) THEN
' Check if variable was declared
check = Search(g_CFILE$, CONCAT$("void* __b2c__dlopen__pointer_", ptr$, ";"), 0)
IF check < 0 THEN
WRITELN "void* __b2c__dlopen__pointer_", ptr$, ";" TO g_CFILE
WRITELN "__b2c__dlopen__pointer_", ptr$, " = dlopen(", lib$, ", RTLD_LAZY);" TO g_CFILE
END IF
WRITELN "if(__b2c__dlopen__pointer_", ptr$, " == NULL){if(!__b2c__trap){ERROR = 3;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
' Check if token was declared
check = Search(g_HFILE$, CONCAT$(type$, "(\\*", sym$, ")"), g_HEADER_SEARCHPOS)
IF check < 0 THEN
WRITELN type$, "(*", sym$, ")(", MID$(token$, INSTR(token$, "(") + 1), ");" TO g_HFILE
END IF
' Translate to C function
WRITELN "*(", type$, "**) (&", sym$, ") = dlsym(__b2c__dlopen__pointer_", ptr$, ", \"", sym$, "\");" TO g_CFILE
WRITELN "if(", sym$, " == NULL) {if(!__b2c__trap){ERROR = 4;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
END IF
' Make symbol known to parser
g_IMPORTED$ = CONCAT$(sym$, " ", g_IMPORTED$)
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Declare(STRING arg$)
LOCAL var$, type$, new$, value$, array$
LOCAL i, dim, check, option
' Check on a GLOBAL RECORD
IF INSTR(arg$, "RECORD ") THEN
' Translate to C typedef struct
g_RECORDNAME$ = CONCAT$("RECORD_", STR$(g_COUNTER))
WRITELN "struct ", g_RECORDNAME$, "{" TO g_HFILE
g_RECORDVAR$ = MID$(CHOP$(arg$), INSTR(CHOP$(arg$), " ") + 1)
' Store current function name
IF LEN(g_FUNCNAME$) > 0 THEN
g_RECORDCACHE$ = g_FUNCNAME$
g_FUNCNAME$ = ""
END IF
ELSE
' Get the variablename and type
IF INSTR(arg$, " TYPE ") THEN
var$ = CHOP$(MID$(arg$, 1, INSTR(arg$, " TYPE ")))
type$ = CHOP$(MID$(arg$, INSTR(arg$, " TYPE ") + 6))
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$, g_HEADER_SEARCHPOS)
ELSE check = FALSE
IF ISTRUE(check) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: variable in DECLARE or GLOBAL statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "' was defined previously!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' If array, increase dimensions when OPTION BASE is set
IF REGEX(var$, "\\[.*\\]") AND NOT(INSTR(var$, "=")) THEN
new$ = ""
REPEAT
new$ = CONCAT$(new$, LEFT$(var$, INSTR(var$, "[") - 1), "[")
value$ = MID$(var$, INSTR(var$, "[") + 1)
new$ = CONCAT$(new$, MID$(value$, 1, INSTR(value$, "]") - 1), "+", STR$(g_OPTION_BASE), "]")
var$ = MID$(var$, INSTR(var$, "]") + 1)
UNTIL NOT(REGEX(var$, "\\[.*\\]"))
var$ = new$
END IF
' Check for associative array
IF INSTR(arg$, " ASSOC ") THEN
SPLIT var$ BY "," TO str$ SIZE dim
FOR i = 1 TO dim
WRITELN "struct __b2c__", CHOP$(str$[i]), "_type {char *key; /* noparse */ ", type$, " value; /* noparse */ };" TO g_HFILE
WRITELN "struct __b2c__", CHOP$(str$[i]), "_type *__b2c__", CHOP$(str$[i]), " = { NULL }; long __b2c__", CHOP$(str$[i]), "_idx = 0;" TO g_HFILE
WRITELN "static int __b2c__", CHOP$(str$[i]), "_comp(const void *__b2c__m1, const void *__b2c__m2){ " TO g_HFILE
WRITELN "struct __b2c__", CHOP$(str$[i]), "_type *__b2c__mi1 = (struct __b2c__", CHOP$(str$[i]), "_type *) __b2c__m1;" TO g_HFILE
WRITELN "struct __b2c__", CHOP$(str$[i]), "_type *__b2c__mi2 = (struct __b2c__", CHOP$(str$[i]), "_type *) __b2c__m2;" TO g_HFILE
WRITELN "if(__b2c__mi1->key == NULL && __b2c__mi2->key == NULL) return 0;" TO g_HFILE
WRITELN "if(__b2c__mi1->key == NULL && __b2c__mi2->key != NULL) return -1;" TO g_HFILE
WRITELN "if(__b2c__mi1->key != NULL && __b2c__mi2->key == NULL) return 1;" TO g_HFILE
WRITELN "return strcmp(__b2c__mi1->key, __b2c__mi2->key); }" TO g_HFILE
WRITELN "struct __b2c__", CHOP$(str$[i]), "_type * __b2c__", CHOP$(str$[i]), "_exist (char *__b2c__index){struct __b2c__", CHOP$(str$[i]), "_type __b2c__", CHOP$(str$[i]), "_key, *__b2c__", CHOP$(str$[i]), "__result;" TO g_HFILE
WRITELN "qsort(__b2c__", CHOP$(str$[i]), ", __b2c__", CHOP$(str$[i]), "_idx, sizeof(struct __b2c__", CHOP$(str$[i]), "_type), __b2c__", CHOP$(str$[i]), "_comp);" TO g_HFILE
WRITELN "__b2c__", CHOP$(str$[i]), "_key.key = __b2c__index; __b2c__", CHOP$(str$[i]), "__result = bsearch(&__b2c__", CHOP$(str$[i]), "_key, __b2c__", CHOP$(str$[i]), "," TO g_HFILE
WRITELN "__b2c__", CHOP$(str$[i]), "_idx, sizeof(struct __b2c__", CHOP$(str$[i]), "_type), __b2c__", CHOP$(str$[i]), "_comp);" TO g_HFILE
WRITELN "return(__b2c__", CHOP$(str$[i]), "__result); }" TO g_HFILE
WRITELN "void __b2c__", CHOP$(str$[i]), "__add(char *__b2c__index){__b2c__", CHOP$(str$[i]), "_idx++;" TO g_HFILE
WRITELN "__b2c__", CHOP$(str$[i]), " = (struct __b2c__", CHOP$(str$[i]), "_type *) realloc (__b2c__", CHOP$(str$[i]), ", __b2c__", CHOP$(str$[i]), "_idx * sizeof (struct __b2c__", CHOP$(str$[i]), "_type));" TO g_HFILE
WRITELN "__b2c__", CHOP$(str$[i]), "[__b2c__", CHOP$(str$[i]), "_idx - 1].key = strdup (__b2c__index); __b2c__", CHOP$(str$[i]), "[__b2c__", CHOP$(str$[i]), "_idx-1].value = 0;}" TO g_HFILE
WRITELN "void __b2c__", CHOP$(str$[i]), "__del(char *__b2c__index){struct __b2c__", CHOP$(str$[i]), "_type *__b2c__", CHOP$(str$[i]), "__location = __b2c__", CHOP$(str$[i]), "_exist(__b2c__index);" TO g_HFILE
WRITELN "if(__b2c__", CHOP$(str$[i]), "__location != NULL) {free(__b2c__", CHOP$(str$[i]), "__location->key); __b2c__", CHOP$(str$[i]), "__location->key = NULL;} }" TO g_HFILE
WRITELN type$, " ", CHOP$(str$[i]), "(char *__b2c__index){struct __b2c__", CHOP$(str$[i]), "_type __b2c__", CHOP$(str$[i]), "_key, *__b2c__", CHOP$(str$[i]), "__result;" TO g_HFILE
WRITELN "qsort(__b2c__", CHOP$(str$[i]), ", __b2c__", CHOP$(str$[i]), "_idx, sizeof(struct __b2c__", CHOP$(str$[i]), "_type), __b2c__", CHOP$(str$[i]), "_comp);" TO g_HFILE
WRITELN "__b2c__", CHOP$(str$[i]), "_key.key = __b2c__index; __b2c__", CHOP$(str$[i]), "__result = bsearch(&__b2c__", CHOP$(str$[i]), "_key, __b2c__", CHOP$(str$[i]), "," TO g_HFILE
WRITELN "__b2c__", CHOP$(str$[i]), "_idx, sizeof(struct __b2c__", CHOP$(str$[i]), "_type), __b2c__", CHOP$(str$[i]), "_comp);" TO g_HFILE
IF INSTR(str$[i], g_STRINGSIGN$) OR INSTR(type$, "STRING") OR INSTR(type$, "char*") THEN
WRITELN "if(__b2c__", CHOP$(str$[i]), "__result == NULL) return(\"\"); return __b2c__", CHOP$(str$[i]), "__result->value;}" TO g_HFILE
ELSE
WRITELN "if(__b2c__", CHOP$(str$[i]), "__result == NULL) return(0); return __b2c__", CHOP$(str$[i]), "__result->value;}" TO g_HFILE
END IF
NEXT
' Check for dynamic array declaration
ELIF ISTRUE(LEN(array$)) THEN
SPLIT var$ BY "," TO str$ SIZE dim
FOR i = 1 TO dim
WRITELN type$, "* ", str$[i], ";" TO g_HFILE
WRITELN str$[i], " = (", type$, "*)calloc(", array$, "+", g_OPTION_BASE, ", sizeof(", type$, "));" TO g_CFILE
' Initialize strings
IF REGEX(type$, "STRING|char\\*$") OR INSTR(var$, g_STRINGSIGN$) THEN
WRITELN "long __b2c_array_", CHOP$(str$[i]), "; /* noparse */" TO g_HFILE
WRITELN "__b2c_array_", CHOP$(str$[i]), " = ", array$, ";" TO g_CFILE
WRITELN "for(__b2c__ctr=0; __b2c__ctr<", array$, "+", g_OPTION_BASE, "; __b2c__ctr++)", str$[i], "[__b2c__ctr] = calloc(1, sizeof(char));" TO g_CFILE
END IF
NEXT
' Check if var is string var
ELIF ( INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*") ) AND NOT(INSTR(var$, "=")) THEN
check = Search(g_HFILE$, CONCAT$("char *", var$, " = NULL;"), g_HEADER_SEARCHPOS)
IF check < 0 THEN
SPLIT CHOP$(var$) BY "," TO str$ SIZE dim
FOR i = 1 TO dim
IF INSTR(str$[i], "[") THEN
WRITELN "char *", CHOP$(str$[i]), " = { NULL };" TO g_HFILE
ELSE
WRITELN "char *", CHOP$(str$[i]), " = NULL; " TO g_HFILE
' Pointer var should not be initialized
IF INSTR(str$[i], g_STRINGSIGN$) THEN WRITELN CHOP$(str$[i]), " = calloc(1, sizeof(char));" TO g_CFILE
END IF
NEXT
END IF
' Var is string array assignment
ELIF ( INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*") ) AND INSTR(var$, "=") THEN
WRITELN "char* ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE
option = g_OPTION_BASE
WHILE option > 0
WRITELN " \"\", " TO g_HFILE
DECR option
WEND
WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE
' Assume char assignment or number
ELSE
IF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN
SPLIT var$ BY "," TO str$ SIZE dim
FOR i = 1 TO dim
WRITELN type$, " ", str$[i], " = { 0 };" TO g_HFILE
NEXT
ELIF INSTR(var$, "[") AND INSTR(var$, "=") THEN
WRITELN type$, " ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE
option = g_OPTION_BASE
WHILE option > 0
WRITELN " 0, " TO g_HFILE
DECR option
WEND
WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE
ELIF NOT(INSTR(var$, "=")) AND NOT(INSTR(var$, "(")) AND REGEX(type$, "char|short|int|long|double|float|NUMBER|FLOATING") THEN
WRITELN type$, " ", var$, ";" TO g_HFILE
WRITELN REPLACE$(var$, ",", "="), " = 0;" TO g_CFILE
ELSE
WRITELN type$, " ", var$, ";" TO g_HFILE
END IF
ENDIF
ENDIF
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Local(STRING arg$)
LOCAL var$, type$, new$, value$, dim$, array$
LOCAL check, i, dim
' 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$, 0)
ELSE check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS)
END IF
IF ISTRUE(check) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: variable in LOCAL statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "' was defined previously!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' If array, increase dimensions when OPTION BASE is set
IF REGEX(var$, "\\[.*\\]") AND NOT(INSTR(var$, "=")) THEN
new$ = ""
REPEAT
new$ = CONCAT$(new$, LEFT$(var$, INSTR(var$, "[") - 1), "[")
value$ = MID$(var$, INSTR(var$, "[") + 1)
new$ = CONCAT$(new$, MID$(value$, 1, INSTR(value$, "]") - 1), "+", STR$(g_OPTION_BASE), "]")
var$ = MID$(var$, INSTR(var$, "]") + 1)
UNTIL NOT(REGEX(var$, "\\[.*\\]"))
var$ = new$
END IF
' Check for dynamic array declaration
IF ISTRUE(LEN(array$)) THEN
SPLIT var$ BY "," TO str$ SIZE dim
FOR i = 1 TO dim
IF ISTRUE(LEN(g_RECORDNAME$)) THEN
IF ISTRUE(LEN(g_FUNCNAME$)) THEN
WRITELN type$, "* ", str$[i], ";" TO g_CFILE
g_LOCALSTRINGS$ = CONCAT$(g_LOCALSTRINGS$, " ", g_RECORDVAR$, ".", CHOP$(str$[i]))
ELSE
WRITELN type$, "* ", str$[i], ";" TO g_HFILE
END IF
g_RECORDEND_BODY$ = CONCAT$(g_RECORDEND_BODY$, " ", g_RECORDVAR$, ".", CHOP$(str$[i]), " = (", type$, "*)calloc(", array$, "+", STR$(g_OPTION_BASE), ", sizeof(", type$, "));")
ELSE
IF ISTRUE(LEN(g_FUNCNAME$)) THEN
WRITELN type$, "* ", str$[i], ";" TO g_CFILE
g_LOCALSTRINGS$ = CONCAT$(g_LOCALSTRINGS$, " ", CHOP$(str$[i]))
ELSE
WRITELN type$, "* ", str$[i], ";" TO g_HFILE
END IF
WRITELN str$[i], " = (", type$, "*)calloc(", array$, "+", g_OPTION_BASE, ", sizeof(", type$, "));" TO g_CFILE
END IF
' Initialize strings
IF REGEX(type$, "STRING|char\\*$") OR INSTR(var$, g_STRINGSIGN$) THEN
IF ISTRUE(LEN(g_RECORDNAME$)) THEN
IF ISTRUE(LEN(g_FUNCNAME$)) THEN
g_RECORDEND_BODY$ = CONCAT$(g_RECORDEND_BODY$, " long __b2c_array_", CHOP$(str$[i]), "; __b2c_array_", CHOP$(str$[i]), " = ", array$, "; for(__b2c__ctr=0; __b2c__ctr<", array$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++)", g_RECORDVAR$, ".", str$[i], "[__b2c__ctr] = calloc(1, sizeof(char));")
g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, " for(__b2c__ctr=0; __b2c__ctr<__b2c_array_", CHOP$(str$[i]), "+", STR$(g_OPTION_BASE), "; __b2c__ctr++) if(", g_RECORDVAR$, ".", str$[i], "[__b2c__ctr]!=NULL){free(", g_RECORDVAR$, ".", str$[i], "[__b2c__ctr]);}")
ELSE
g_RECORDEND_BODY$ = CONCAT$(g_RECORDEND_BODY$, "__b2c_array_", CHOP$(str$[i]), " = ", array$, "; for(__b2c__ctr=0; __b2c__ctr<", array$, "+", STR$(g_OPTION_BASE), "; __b2c__ctr++)", g_RECORDVAR$, ".", str$[i], "[__b2c__ctr] = calloc(1, sizeof(char));")
g_RECORDEND_HEADER$ = CONCAT$(g_RECORDEND_HEADER$, "long __b2c_array_", CHOP$(str$[i]), ";")
END IF
ELSE
IF ISTRUE(LEN(g_FUNCNAME$)) THEN
WRITELN "long __b2c_array_", CHOP$(str$[i]), "; /* noparse */" TO g_CFILE
g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, " for(__b2c__ctr=0; __b2c__ctr<__b2c_array_", CHOP$(str$[i]), "+", STR$(g_OPTION_BASE), "; __b2c__ctr++) if(", str$[i], "[__b2c__ctr]!=NULL){free(", str$[i], "[__b2c__ctr]);}")
ELSE
WRITELN "long __b2c_array_", CHOP$(str$[i]), "; /* noparse */" TO g_HFILE
END IF
WRITELN "__b2c_array_", CHOP$(str$[i]), " = ", array$, ";" TO g_CFILE
WRITELN "for(__b2c__ctr=0; __b2c__ctr<", array$, "+", g_OPTION_BASE, "; __b2c__ctr++)", str$[i], "[__b2c__ctr] = calloc(1, sizeof(char));" TO g_CFILE
END IF
END IF
NEXT
' Check if var is string var
ELIF ( REGEX(type$, "STRING|char\\*$") OR INSTR(var$, g_STRINGSIGN$) ) AND NOT(INSTR(var$, "=")) AND NOT(REGEX(type$, ".+\\[.+\\$\\]")) THEN
check = Search(g_HFILE$, CONCAT$("char *", var$, " = NULL;"), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
check = Search(g_CFILE$, CONCAT$("char *", var$, " = NULL;"), 0)
ENDIF
IF check < 0 THEN
SPLIT var$ BY "," TO str$ SIZE dim
FOR i = 1 TO dim
' Check on multidimensional stringarrays
IF REGEX(str$[i], "\\[.*\\]\\[") THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: multidimensional stringarrays at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "' are not supported!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Are we in a function?
IF ISTRUE(LEN(g_FUNCNAME$)) THEN
IF ISTRUE(LEN(g_RECORDNAME$)) THEN
IF REGEX(str$[i], "\\[.*\\]") THEN
WRITELN "char *", CHOP$(str$[i]), ";" TO g_CFILE
dim$ = MID$(str$[i], INSTR(str$[i], "[") + 1)
g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, " for(__b2c__ctr=0; __b2c__ctr<", LEFT$(dim$, INSTR(dim$, "]") - 1), "; __b2c__ctr++)if(", g_RECORDVAR$, ".", LEFT$(str$[i], INSTR(str$[i], "[")-1), "[__b2c__ctr]!=NULL){free(", g_RECORDVAR$, ".", LEFT$(str$[i], INSTR(str$[i], "[")-1), "[__b2c__ctr]);}")
ELSE
WRITELN "char *", CHOP$(str$[i]), "; /* noparse */" TO g_CFILE
END IF
ELSE
IF REGEX(str$[i], "\\[.*\\]") THEN
WRITELN "char *", CHOP$(str$[i]), " = { NULL};" TO g_CFILE
dim$ = MID$(str$[i], INSTR(str$[i], "[") + 1)
g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, " for(__b2c__ctr=0; __b2c__ctr<", LEFT$(dim$, INSTR(dim$, "]") - 1), "; __b2c__ctr++)if(", g_WITHVAR$, LEFT$(str$[i], INSTR(str$[i], "[")-1), "[__b2c__ctr]!=NULL){free(", g_WITHVAR$, LEFT$(str$[i], INSTR(str$[i], "[")-1), "[__b2c__ctr]);}")
ELSE
WRITELN "char *", CHOP$(str$[i]), " = NULL;" TO g_CFILE
' Pointer var should not be initialized
IF INSTR(str$[i], g_STRINGSIGN$) THEN
WRITELN CHOP$(str$[i]), " = calloc(1, sizeof(char));" TO g_CFILE
g_LOCALSTRINGS$ = CONCAT$(g_LOCALSTRINGS$, " ", CHOP$(str$[i]))
END IF
END IF
END IF
' We are in the mainprogram
ELSE
IF ISTRUE(LEN(g_RECORDNAME$)) THEN
WRITELN "char *", CHOP$(str$[i]), "; /* noparse */" TO g_HFILE
ELSE
IF REGEX(str$[i], "\\[.*\\]") THEN
WRITELN "char *", CHOP$(str$[i]), " = { NULL };" TO g_CFILE
ELSE
WRITELN "char *", CHOP$(str$[i]), " = NULL; " TO g_HFILE
' Pointer var should not be initialized
IF INSTR(str$[i], g_STRINGSIGN$) THEN WRITELN CHOP$(str$[i]), " = calloc(1, sizeof(char));" TO g_CFILE
END IF
END IF
END IF
NEXT
END IF
ELIF ( INSTR(var$, g_STRINGSIGN$) OR REGEX(type$, "STRING|char\\*") ) AND INSTR(var$, "=") THEN
IF ISTRUE(LEN(g_FUNCNAME$)) THEN
' String array assignment
WRITELN "char* ", MID$(var$, 1, INSTR(var$, "{")) TO g_CFILE
option = g_OPTION_BASE
WHILE option > 0
WRITELN " \"\", " TO g_CFILE
DECR option
WEND
WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_CFILE
ELSE
' String array assignment
WRITELN "char* ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE
option = g_OPTION_BASE
WHILE option > 0
WRITELN " \"\", " TO g_HFILE
DECR option
WEND
WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE
END IF
' Assume number
ELSE
IF ISTRUE(LEN(g_FUNCNAME$)) THEN
IF ISTRUE(LEN(g_RECORDNAME$)) THEN
WRITELN type$, " ", var$, "; /* noparse */" TO g_CFILE
ELSE
IF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN
SPLIT var$ BY "," TO str$ SIZE dim
FOR i = 1 TO dim
WRITELN type$, " ", str$[i], " = { 0 };" TO g_CFILE
NEXT
ELIF INSTR(var$, "[") AND INSTR(var$, "=") THEN
' Numeric array assignment
WRITELN type$, " ", MID$(var$, 1, INSTR(var$, "{")) TO g_CFILE
option = g_OPTION_BASE
WHILE option > 0
WRITELN " 0, " TO g_CFILE
DECR option
WEND
WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_CFILE
ELIF NOT(INSTR(var$, "=")) AND NOT(INSTR(var$, "(")) AND REGEX(type$, "char|short|int|long|double|float|NUMBER|FLOATING") THEN
WRITELN type$, " ", var$, ";" TO g_CFILE
WRITELN REPLACE$(var$, ",", "="), " = 0;" TO g_CFILE
ELSE
WRITELN type$, " ", var$, ";" TO g_CFILE
END IF
END IF
ELSE
IF ISTRUE(LEN(g_RECORDNAME$)) THEN
WRITELN type$, " ", var$, "; /* noparse */" TO g_HFILE
ELSE
IF INSTR(var$, "[") AND NOT(INSTR(var$, "=")) THEN
SPLIT var$ BY "," TO str$ SIZE dim
FOR i = 1 TO dim
WRITELN type$, " ", str$[i], " = { 0 };" TO g_HFILE
NEXT
ELIF INSTR(var$, "[") AND INSTR(var$, "=") THEN
' Numeric array assignment
WRITELN type$, " ", MID$(var$, 1, INSTR(var$, "{")) TO g_HFILE
option = g_OPTION_BASE
WHILE option > 0
WRITELN " 0, " TO g_HFILE
DECR option
WEND
WRITELN MID$(var$, INSTR(var$, "{")+1), ";" TO g_HFILE
ELIF NOT(INSTR(var$, "=")) AND NOT(INSTR(var$, "(")) AND REGEX(type$, "char|short|int|long|double|float|NUMBER|FLOATING") THEN
WRITELN type$, " ", var$, ";" TO g_HFILE
WRITELN REPLACE$(var$, ",", "="), " = 0;" TO g_CFILE
ELSE
WRITELN type$, " ", var$, ";" TO g_HFILE
END IF
END IF
END IF
END IF
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Read(STRING arg$)
LOCAL check
LOCAL type$
' Check if we have an argument at all
IF ISFALSE(LEN(CHOP$(arg$))) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty READ at at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check type of var, string?
IF EQUAL(RIGHT$(arg$, LEN(g_STRINGSIGN$)), g_STRINGSIGN$) THEN
check = Search(g_HFILE$, CONCAT$("char *", arg$, " = NULL;"), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
check = Search(g_CFILE$, CONCAT$("char *", arg$, " = NULL;"), 0)
ENDIF
IF check < 0 THEN WRITELN "char *", arg$, " = NULL;" TO g_HFILE
' Convert to C
WRITELN arg$, " = (char*)realloc(", arg$, ", (strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1)*sizeof(char));" TO g_CFILE
WRITELN "strcpy(", arg$, ", __b2c__stringarray[__b2c__stringarray_ptr]);" TO g_CFILE
WRITELN "__b2c__stringarray_ptr++;" TO g_CFILE
ELSE
' Variable may not be array, these should be defined with DECLARE
IF NOT(REGEX(arg$, "\\[.*\\]")) AND NOT(INSTR(arg$, ".")) THEN
' Not declared? Assume long
check = Check_Declared(g_HFILE$, arg$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, arg$, 0)
IF ISFALSE(check) THEN WRITELN "long ", arg$, ";" TO g_HFILE
END IF
' See how var was declared
type$ = Check_Type$(g_HFILE$, arg$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN
type$ = Check_Type$(g_CFILE$, arg$, 0)
END IF
' Convert to C
IF INSTR(type$, "char* ") OR INSTR(type$, "char *") OR INSTR(type$, "STRING ") THEN
WRITELN arg$, " = (char*)realloc(", arg$, ", (strlen(__b2c__stringarray[__b2c__stringarray_ptr])+1)*sizeof(char));" TO g_CFILE
WRITELN "strcpy(", arg$, ", __b2c__stringarray[__b2c__stringarray_ptr]);" TO g_CFILE
WRITELN "__b2c__stringarray_ptr++;" TO g_CFILE
ELSE
WRITELN arg$, " = (", LEFT$(type$, INSTR(type$, " ")), ")__b2c__floatarray[__b2c__floatarray_ptr];" TO g_CFILE
WRITELN "__b2c__floatarray_ptr++;" TO g_CFILE
END IF
END IF
LABEL End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty COLOR at at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
SPLIT arg$ BY " " TO element$ SIZE dim
' Check if we need to reset
IF EQUAL(element$[1], "RESET") THEN
WRITELN "fprintf(stdout,\"\\033[0m\");" TO g_CFILE
ELIF EQUAL(element$[1], "INTENSE") THEN
WRITELN "fprintf(stdout,\"\\033[1m\");" TO g_CFILE
ELIF EQUAL(element$[1], "INVERSE") THEN
WRITELN "fprintf(stdout,\"\\033[7m\");" TO g_CFILE
ELIF EQUAL(element$[1], "NORMAL") THEN
WRITELN "fprintf(stdout,\"\\033[22m\");" TO g_CFILE
' Check if TO is available
ELIF NOT(INSTR(arg$, " TO ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: Missing TO in COLOR statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
' Get the target and colorname
SELECT element$[1]
CASE "FG"
BFG$ = "3"
CASE "BG"
BFG$ = "4"
DEFAULT
IF REGEX(element$[1], "0|1") THEN BFG$ = STR$(VAL(element$[1]) + 3)
ELSE BFG$ = element$[1]
END SELECT
SELECT element$[3]
CASE "BLACK"
COL$ = "0"
CASE "RED"
COL$ = "1"
CASE "GREEN"
COL$ = "2"
CASE "YELLOW"
COL$ = "3"
CASE "BLUE"
COL$ = "4"
CASE "MAGENTA"
COL$ = "5"
CASE "CYAN"
COL$ = "6"
CASE "WHITE"
COL$ = "7"
DEFAULT
COL$ = element$[3]
END SELECT
' Now select color
WRITELN "fprintf(stdout,\"\\033[%ld%ldm\", (long)", BFG$, ", (long)", COL$, ");" TO g_CFILE
END IF
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Gotoxy(STRING arg$)
LOCAL dim
' Check if we have an argument at all
IF ISFALSE(LEN(CHOP$(arg$))) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty GOTOXY at at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the target and colorname
SPLIT arg$ BY "," TO element$ SIZE dim
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing coordinate in GOTOXY at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Translate to C
WRITELN "fprintf(stdout, \"\\033[%ld;%ldH\",(long)(", CHOP$(element$[2]), "), (long)(", CHOP$(element$[1]), ")); fflush(stdout);" TO g_CFILE
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Split(STRING arg$)
LOCAL source$, rest$, by$, to$, size$
LOCAL check
' Check if we have an argument at all
IF ISFALSE(LEN(CHOP$(arg$))) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty SPLIT at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check if BY is available
IF NOT(INSTR(arg$, " BY ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: Missing BY in SPLIT statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check if TO is available
IF NOT(INSTR(arg$, " TO ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: Missing TO in SPLIT statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check if SIZE is available
IF NOT(INSTR(arg$, " SIZE ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: Missing SIZE in SPLIT statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the source string
source$ = CHOP$(LEFT$(arg$, INSTR(arg$, " BY ") - 1))
rest$ = MID$(arg$, INSTR(arg$, " BY ") + 4)
by$ = CHOP$(LEFT$(rest$, INSTR(rest$, " TO ") - 1))
rest$ = MID$(rest$, INSTR(rest$, " TO ") + 4)
to$ = CHOP$(LEFT$(rest$, INSTR(rest$, " SIZE ") - 1))
size$ = CHOP$(MID$(rest$, INSTR(rest$, " SIZE ") + 6))
' Variable may not be array, these should be defined with DECLARE
IF NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) THEN
check = Check_Declared(g_HFILE$, size$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, size$, 0)
IF ISFALSE(check) THEN WRITELN "long ", size$, ";" TO g_HFILE
END IF
' Translate to C code
IF ISTRUE(LEN(g_FUNCNAME$)) THEN
IF NOT(INSTR(g_STRINGARGS$, CONCAT$("**", to$))) THEN
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, " char **", to$, " = NULL; int __b2c__split__", to$, " = ", STR$(g_OPTION_BASE), ";")
END IF
ELSE
check = Search(g_HFILE$, CONCAT$(to$, " = NULL;"), g_HEADER_SEARCHPOS)
IF check < 0 THEN
WRITELN "char **", to$, " = NULL; int __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_HFILE
END IF
END IF
' If the split array was used before in a loop, clear it
WRITELN "if(", to$, " != NULL) {for(__b2c__ctr=", g_OPTION_BASE, "; __b2c__ctr<=__b2c__split__", to$, "; __b2c__ctr++) if(", to$, "[__b2c__ctr]!=NULL)" TO g_CFILE
WRITELN "{free(", to$, "[__b2c__ctr]);} free(", to$, "); ", to$, " = NULL;} __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_CFILE
' Run the SPLIT code
WRITELN "if (", source$, " != NULL && strlen(", source$, ") > 0 && ", by$, " != NULL && strlen(", by$, ")>0){__b2c__split_tmp = strdup(", source$, "); __b2c__split_ptr = __b2c__split_tmp; while((__b2c__split = strstr(__b2c__split_tmp, ", by$, ")) != NULL)" TO g_CFILE
WRITELN "{if(__b2c__split-__b2c__split_tmp >= 0) {", to$, " = (char **)realloc(", to$, ", (__b2c__split__", to$, " + 1) * sizeof(char*)); if(__b2c__split-__b2c__split_tmp == 0) {", to$, "[__b2c__split__", to$, "] = calloc(1, sizeof(char)); if (__b2c__collapse == 0)" TO g_CFILE
WRITELN "__b2c__split__", to$, "++; else free(", to$, "[__b2c__split__", to$, "]);} else ", to$, "[__b2c__split__", to$, "++] = __b2c__strndup(__b2c__split_tmp, __b2c__split-__b2c__split_tmp);}" TO g_CFILE
WRITELN "__b2c__split_tmp = __b2c__split + strlen(", by$, ");} if(strlen(__b2c__split_tmp) >= 0) {", to$, " = (char **)realloc(", to$, ", (__b2c__split__", to$, " + 1) * sizeof(char*)); if(strlen(__b2c__split_tmp) == 0) {" TO g_CFILE
WRITELN to$, "[__b2c__split__", to$, "] = calloc(1, sizeof(char)); if (__b2c__collapse == 0) __b2c__split__", to$, "++; else free(", to$, "[__b2c__split__", to$, "]);}" TO g_CFILE
WRITELN "else ", to$, "[__b2c__split__", to$, "++] = strdup(__b2c__split_tmp);} free(__b2c__split_ptr);} ", size$, " = __b2c__split__", to$, " - ", g_OPTION_BASE, "; if(__b2c__split__", to$, " > 0) __b2c__split__", to$, "--;" TO g_CFILE
' Add declared array to array list if we are in a function
IF ISTRUE(LEN(g_FUNCNAME$)) AND NOT(INSTR(g_STRINGARRAYS$, CONCAT$(to$, "["))) THEN
g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, " if(", to$, "!= NULL){for(__b2c__ctr=", STR$(g_OPTION_BASE), ";__b2c__ctr<=__b2c__split__", to$, ";__b2c__ctr++) if(", to$, "[__b2c__ctr]!=NULL){free(", to$, "[__b2c__ctr]);}free(", to$, ");}")
END IF
LABEL End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty SORT at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check on SIZE argument
IF INSTR(arg$, "SIZE") THEN
dim$ = CHOP$(MID$(arg$, INSTR(arg$, "SIZE") + 5))
var$ = CHOP$(LEFT$(arg$, INSTR(arg$, "SIZE") - 1))
ELSE
var$ = arg$
END IF
' Check on DOWN argument
IF INSTR(arg$, "DOWN") THEN
IF LEN(dim$) > 0 THEN dim$ = CHOP$(LEFT$(dim$, INSTR(dim$, "DOWN") - 1))
var$ = CHOP$(LEFT$(var$, INSTR(var$, "DOWN") - 1))
down$ = "_down"
ELSE
down$ = ""
END IF
' Declared before?
IF INSTR(var$, g_STRINGSIGN$) THEN
check = Search(g_HFILE$, CONCAT$("char *", var$, "["), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
check = Search(g_CFILE$, CONCAT$("char *", var$, "["), 0)
ENDIF
ELSE
check = Check_Declared(g_HFILE$, var$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, var$, 0)
END IF
' Verify if the array was declared at SPLIT
IF check < 0 THEN
check = Search(g_HFILE$, CONCAT$("__b2c__split__", var$), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
check = Search(g_CFILE$, CONCAT$("__b2c__split__", var$), 0)
ENDIF
IF ISFALSE(check) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: argument to SORT not an array at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELIF LEN(dim$) IS 0 THEN
dim$ = CONCAT$("__b2c__split__", var$, "+1")
END IF
ELIF LEN(dim$) IS 0 THEN
' See how var was declared
type$ = Check_Type$(g_HFILE$, CONCAT$(var$, "["), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN
type$ = Check_Type$(g_CFILE$, CONCAT$(var$, "["), 0)
ENDIF
dim$ = MID$(type$, INSTR(type$, "[") + 1, INSTR(type$, "]") - INSTR(type$, "[") - 1)
END IF
' Check if we have a string
IF INSTR(var$, g_STRINGSIGN$) THEN
WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, ", sizeof(char*), __b2c__sortstr", down$, ");" TO g_CFILE
' It is a value
ELSE
' See how var was declared
type$ = Check_Type$(g_HFILE$, CONCAT$(var$, "["), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN type$ = Check_Type$(g_CFILE$, CONCAT$(var$, "["), 0)
IF INSTR(type$, "double ") OR INSTR(type$, "FLOATING ") THEN
WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, ", sizeof(double), __b2c__sortnrd", down$, ");" TO g_CFILE
ELIF INSTR(type$, "float ") THEN
WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, ", sizeof(float), __b2c__sortnrf", down$, ");" TO g_CFILE
ELIF INSTR(type$, "long ") OR INSTR(type$, "NUMBER ") THEN
WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, ", sizeof(long), __b2c__sortnrl", down$, ");" TO g_CFILE
ELSE
WRITELN "qsort(&", var$, "[", g_OPTION_BASE, "], ", dim$, ", sizeof(int), __b2c__sortnri", down$, ");" TO g_CFILE
END IF
END IF
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Alias(STRING arg$)
LOCAL dim
' Check if we have an argument at all
IF ISFALSE(LEN(CHOP$(arg$))) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty ALIAS at at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the target and colorname
SPLIT REPLACE$(arg$, CHR$(34), "") BY "TO" TO element$ SIZE dim
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing TO in ALIAS statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Translate to C
WRITELN "#define ", element$[2], " ", element$[1] TO g_HFILE
g_IMPORTED$ = CONCAT$(element$[2], " ", g_IMPORTED$)
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Lookup(STRING arg$)
LOCAL source$, rest$, to$, size$
LOCAL check
' Check if we have an argument at all
IF ISFALSE(LEN(CHOP$(arg$))) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty LOOKUP at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check if TO is available
IF NOT(INSTR(arg$, " TO ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: Missing TO in LOOKUP statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check if SIZE is available
IF NOT(INSTR(arg$, " SIZE ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: Missing SIZE in LOOKUP statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the source string
source$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TO ") - 1))
rest$ = MID$(arg$, INSTR(arg$, " TO ") + 4)
to$ = CHOP$(LEFT$(rest$, INSTR(rest$, " SIZE ") - 1))
size$ = CHOP$(MID$(rest$, INSTR(rest$, " SIZE ") + 6))
' Variable may not be array, these should be defined with DECLARE
IF NOT(REGEX(size$, "\\[.*\\]")) AND NOT(INSTR(size$, ".")) THEN
check = Check_Declared(g_HFILE$, size$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(check) THEN check = Check_Declared(g_CFILE$, size$, 0)
IF ISFALSE(check) THEN WRITELN "long ", size$, ";" TO g_HFILE
END IF
' Translate to C code
IF ISTRUE(LEN(g_FUNCNAME$)) THEN
IF NOT(INSTR(g_STRINGARGS$, CONCAT$("**", to$))) THEN
g_STRINGARGS$ = CONCAT$(g_STRINGARGS$, " char **", to$, " = NULL; int __b2c__split__", to$, " = ", STR$(g_OPTION_BASE), ";")
END IF
ELSE
check = Search(g_HFILE$, CONCAT$(to$, " = NULL;"), g_HEADER_SEARCHPOS)
IF check < 0 THEN
WRITELN "char **", to$, " = NULL; int __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_HFILE
END IF
END IF
' If the split array was used before in a loop, clear it
WRITELN "if(", to$, " != NULL) {for(__b2c__ctr=", g_OPTION_BASE, "; __b2c__ctr <= __b2c__split__", to$, "; __b2c__ctr++) if(", to$, "[__b2c__ctr]!=NULL)" TO g_CFILE
WRITELN "{free(", to$, "[__b2c__ctr]);} free(", to$, "); ", to$, " = NULL;} __b2c__split__", to$, " = ", g_OPTION_BASE, ";" TO g_CFILE
' Run the LOOKUP code
WRITELN "for(__b2c__ctr = ", g_OPTION_BASE, "; __b2c__ctr < __b2c__", source$, "_idx + ", g_OPTION_BASE, "; __b2c__ctr++)" TO g_CFILE
WRITELN "{", to$, " = (char **)realloc(", to$, ", (__b2c__split__", to$, " + 1) * sizeof(char*));" TO g_CFILE
WRITELN to$, "[__b2c__split__", to$, "++] = strdup(__b2c__", source$, "[__b2c__ctr-", g_OPTION_BASE, "].key);} ", size$, " = __b2c__split__", to$, " - ", g_OPTION_BASE, ";if(__b2c__split__", to$, " > 0) __b2c__split__", to$, "--;" TO g_CFILE
' Add declared array to array list if we are in a function
IF ISTRUE(LEN(g_FUNCNAME$)) AND NOT(INSTR(g_STRINGARRAYS$, CONCAT$(to$, "["))) THEN
g_STRINGARRAYS$ = CONCAT$(g_STRINGARRAYS$, " if(", to$, "!= NULL){for(__b2c__ctr=", STR$(g_OPTION_BASE), ";__b2c__ctr<=__b2c__split__", to$, ";__b2c__ctr++) if(", to$, "[__b2c__ctr]!=NULL){free(", to$, "[__b2c__ctr]);}free(", to$, ");}")
END IF
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Relate(STRING arg$)
LOCAL source$, to$, txt$
LOCAL declared, dim, i
LOCAL thefile TYPE FILE*
' Check if we have an argument at all
IF ISFALSE(LEN(CHOP$(arg$))) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty RELATE at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Check if TO is available
IF NOT(INSTR(arg$, " TO ")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: Missing TO in RELATE statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Get the source string
source$ = CHOP$(LEFT$(arg$, INSTR(arg$, " TO ") - 1))
to$ = CHOP$(MID$(arg$, INSTR(arg$, " TO ") + 4))
' CHeck if declared as ASSOC
OPEN g_HFILE$ FOR READING AS thefile
SEEK thefile OFFSET g_HEADER_SEARCHPOS
WHILE NOT(ENDFILE(thefile)) DO
READLN txt$ FROM thefile
IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 AND NOT(INSTR(txt$, " noparse ")) THEN
declared = REGEX(txt$, CONCAT$("__b2c__", source$, "_type"))
IF ISTRUE(declared) THEN BREAK
END IF
WEND
IF NOT(declared) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: Variable ", source$, " not declared in RELATE statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Assign relations
SPLIT to$ BY "," TO str$ SIZE dim
FOR i = 1 TO dim
SEEK thefile OFFSET g_HEADER_SEARCHPOS
WHILE NOT(ENDFILE(thefile)) DO
READLN txt$ FROM thefile
IF NOT(ENDFILE(thefile)) AND LEN(txt$) > 0 AND NOT(INSTR(txt$, " noparse ")) THEN
declared = REGEX(txt$, CONCAT$("__b2c__", CHOP$(str$[i]), "_type"))
IF ISTRUE(declared) THEN BREAK
END IF
WEND
IF NOT(declared) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: Variable ", CHOP$(str$[i]), " not declared in RELATE statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
g_RELATE$[g_RELATE_CTR] = CONCAT$(source$, " ", CHOP$(str$[i]))
INCR g_RELATE_CTR
NEXT
CLOSE FILE thefile
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Handle_Data(STRING arg$)
LOCAL in_string, pos, escaped, x
' Check if we have an argument at all
IF ISFALSE(LEN(CHOP$(arg$))) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty DATA at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
' Start miniparser
in_string = FALSE
pos = 1
escaped = 0
FOR x = 1 TO LEN(arg$)
IF ISTRUE(EQUAL(MID$(arg$, x, 1), ",")) THEN
IF ISFALSE(in_string) THEN
IF INSTR(MID$(arg$, pos, x-pos), CHR$(34)) THEN
WRITELN MID$(arg$, pos, x-pos), ", " TO STRINGARRAYFILE
ELSE
WRITELN MID$(arg$, pos, x-pos), ", " TO FLOATARRAYFILE
END IF
pos = x+1
escaped = FALSE
END IF
ELIF EQUAL(MID$(arg$, x, 1), "\\") THEN
escaped = TRUE
ELIF ISTRUE(EQUAL(MID$(arg$, x, 1), CHR$(34))) THEN
IF ISFALSE(escaped) THEN
in_string = NOT(in_string)
END IF
escaped = FALSE
ELSE
escaped = FALSE
ENDIF
NEXT
arg$ = MID$(arg$, pos)
' Write last element to file
IF INSTR(arg$, CHR$(34)) THEN
WRITELN arg$, ", " TO STRINGARRAYFILE
ELSE
WRITELN arg$, ", " TO FLOATARRAYFILE
END IF
LABEL End_Func
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
PRINT NL$, "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
PRINT NL$, "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$, CONCAT$(" ", mem$, ";"), g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND check < 0 THEN
check = Search(g_CFILE$, CONCAT$(" ", mem$, ";"), 0)
ENDIF
IF ISFALSE(check) THEN
PRINT NL$, "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$, g_HEADER_SEARCHPOS)
IF LEN(g_FUNCNAME$) > 0 AND ISFALSE(LEN(type$)) THEN
type$ = Check_Type$(g_CFILE$, mem$, 0)
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] = NULL;}" TO g_CFILE
WRITELN "__b2c_array_", mem$, " = ", to$, ";" TO g_CFILE
END IF
END SUB
'----------------------------------------------------------------------------------------------
FUNCTION Count_Lines(STRING file$)
LOCAL lines
LOCAL newfile TYPE FILE*
LOCAL txt$
OPEN file$ FOR READING AS newfile
WHILE NOT(ENDFILE(newfile)) DO
READLN txt$ FROM newfile
INCR lines
WEND
CLOSE FILE newfile
RETURN lines
END FUNCTION
'----------------------------------------------------------------------------------------------
'
' Simple parser to tokenize line.
'
' Each line should begin with a statement.
' The rest of the line may contain functions, these are
' converted using C macros.
'
'----------------------------------------------------------------------------------------------
SUB Parse_Line(STRING statement$)
LOCAL inc$, copy_curfile$, total$, txt$, exp$, lft$, str$, newfeed$
LOCAL dim, i, found, copy_counter, totallines, to_parse, size
LOCAL newfile TYPE FILE*
SPLIT statement$ BY " " TO element$ SIZE dim
IF dim > 0 THEN
' Check if enclosed IF/ELIF/ELSE needs to be closed
IF g_IF_PARSE IS 1 THEN
IF NOT(EQUAL(element$[1], "ELIF")) AND NOT(EQUAL(element$[1], "ELSE")) THEN
WRITELN "}" TO g_CFILE
g_IF_PARSE = 0
END IF
END IF
' In TRACE MODE show linenr and code
IF g_TRACE IS 1 AND NOT(INSTR(statement$, "FUNCTION ")) AND NOT(INSTR(statement$, "SUB ")) THEN
WRITELN "if(__b2c__getch() == 27) exit(EXIT_SUCCESS); /* noparse */" TO g_CFILE
txt$ = REPLACE$(statement$, CHR$(34), "'")
WRITELN "fprintf(stderr, \"", g_CURFILE$, " %d: ", txt$, "\\n\", ", g_COUNTER, "); /* noparse */" TO g_CFILE
END IF
' See if we need to pass C code
IF ISTRUE(g_USE_C) THEN
IF EQUAL(LEFT$(statement$, 8), "END USEC") OR EQUAL(element$[1], "ENDUSEC") THEN
g_USE_C = 0
ELSE
WRITELN statement$ TO g_CFILE
END IF
ELIF EQUAL(LEFT$(element$[1], 2), "#!") THEN
'Do nothing
ELIF EQUAL(LEFT$(element$[1], 1), "'") THEN
'Do nothing
ELIF EQUAL(LEFT$(element$[1], 3), "REM") THEN
'Do nothing
ELSE
SELECT element$[1]
CASE "USEC"
g_USE_C = 1
CASE "PRINT"
Handle_Print(MID$(statement$, INSTR(statement$, "PRINT") + 5))
CASE "INPUT"
Handle_Input(MID$(statement$, INSTR(statement$, "INPUT") + 5))
CASE "FOR"
INCR g_LOOPCTR
Handle_For(MID$(statement$, INSTR(statement$, "FOR") + 3))
CASE "NEXT"
WRITELN "}" TO g_CFILE
IF g_LOOPCTR > 0 THEN
DECR g_LOOPCTR
IF g_LOOPCTR > 0 THEN
WRITELN "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" TO g_CFILE
END IF
END IF
CASE "IF"
' Check if THEN is available
g_IF_PARSE = 0
IF ISFALSE(INSTRREV(statement$, " THEN")) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing THEN in IF statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing THEN in ELIF statement at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
' Translate function to C function
exp$ = Parse_Equation$(MID$(statement$, INSTR(statement$, "ELIF") + 4, INSTRREV(statement$, " THEN") - (INSTR(statement$, "ELIF") + 4)))
WRITELN "} else if(", exp$, "){" TO g_CFILE
IF LEN(CHOP$(MID$(statement$, INSTRREV(statement$, " THEN") + 5))) > 0 THEN
CALL Tokenize(MID$(statement$, INSTRREV(statement$, " THEN") + 5))
g_IF_PARSE = 1
END IF
END IF
CASE "ELSE"
' Translate function to C function
g_IF_PARSE = 0
WRITELN "} else {" TO g_CFILE
IF LEN(CHOP$(MID$(statement$, INSTR(statement$, " ELSE") + 5))) > 0 THEN
CALL Tokenize(MID$(statement$, INSTR(statement$, " ELSE") + 5))
g_IF_PARSE = 1
END IF
CASE "ENDIF"
WRITELN "}" TO g_CFILE
CASE "WHILE"
INCR g_LOOPCTR
Handle_While(MID$(statement$, INSTR(statement$, "WHILE") + 5))
CASE "WEND"
WRITELN "}" TO g_CFILE
IF g_LOOPCTR > 0 THEN
DECR g_LOOPCTR
IF g_LOOPCTR > 0 THEN
WRITELN "if(__b2c__break_ctr) {__b2c__break_ctr--; if (!__b2c__break_ctr){if(__b2c__break_flag == 1) break; else continue;} else break; }" TO g_CFILE
END IF
END IF
CASE "BREAK"
' Check argument
IF dim > 1 AND VAL(MID$(statement$, INSTR(statement$, "BREAK") + 5)) NE 0 THEN
WRITELN "__b2c__break_ctr = ", MID$(statement$, INSTR(statement$, "BREAK") + 5), "-1; __b2c__break_flag = 1;" TO g_CFILE
END IF
WRITELN "break;" TO g_CFILE
CASE "CONTINUE"
' Check argument
IF dim > 1 AND VAL(MID$(statement$, INSTR(statement$, "CONTINUE") + 8)) NE 0 THEN
WRITELN "__b2c__break_ctr = ", MID$(statement$, INSTR(statement$, "CONTINUE") + 8), "-1; __b2c__break_flag = 2;" TO g_CFILE
END IF
IF VAL(MID$(statement$, INSTR(statement$, "CONTINUE") + 8)) > 1 THEN
WRITELN "break;" TO g_CFILE
ELSE
WRITELN "continue;" TO g_CFILE
END IF
CASE "REPEAT"
INCR g_LOOPCTR
WRITELN "do{" TO g_CFILE
CASE "UNTIL"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty UNTIL at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty SYSTEM at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
WRITELN "SYSTEM (", MID$(statement$, INSTR(statement$, "SYSTEM") + 6), ");" TO g_CFILE
END IF
CASE "SLEEP"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty SLEEP at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
WRITELN "usleep(", MID$(statement$, INSTR(statement$, "SLEEP") + 5), "*1000);" TO g_CFILE
END IF
CASE "OPEN"
Handle_Open(MID$(statement$, INSTR(statement$, "OPEN") + 4))
CASE "CLOSE"
' Check argument
IF dim NE 3 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: erroneous CLOSE at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
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"
WRITELN "close(", element$[3], ");" TO g_CFILE
END SELECT
END IF
CASE "REWIND"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty REWIND at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
WRITELN "rewind(", element$[2], ");" TO g_CFILE
END IF
CASE "MEMREWIND"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty MEMREWIND at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
WRITELN element$[2], " = (char*)__b2c_mem_", element$[2], ";" TO g_CFILE
END IF
CASE "SEEK"
Handle_Seek(CHOP$(MID$(statement$, INSTR(statement$, "SEEK") + 4)))
CASE "READLN"
Handle_Readln(CHOP$(MID$(statement$, INSTR(statement$, "READLN") + 6)))
CASE "WRITELN"
Handle_Writeln(MID$(statement$, INSTR(statement$, "WRITELN") + 7))
CASE "GETBYTE"
Handle_Getbyte(CHOP$(MID$(statement$, INSTR(statement$, "GETBYTE") + 7)))
CASE "PUTBYTE"
Handle_Putbyte(CHOP$(MID$(statement$, INSTR(statement$, "PUTBYTE") + 7)))
CASE "GETFILE"
Handle_Getfile(CHOP$(MID$(statement$, INSTR(statement$, "GETFILE") + 7)))
CASE "GETLINE"
Handle_Getline(CHOP$(MID$(statement$, INSTR(statement$, "GETLINE") + 7)))
CASE "PUTLINE"
Handle_Putline(MID$(statement$, INSTR(statement$, "PUTLINE") + 7))
CASE "END"
IF dim > 1 THEN
SELECT element$[2]
CASE "IF"
WRITELN "}" TO g_CFILE
CASE "RECORD"
IF LEN(g_FUNCNAME$) > 0 THEN
WRITELN "};" TO g_CFILE
WRITELN "struct ", g_RECORDNAME$, " ", g_RECORDVAR$, " = { } ;" TO g_CFILE
ELSE
WRITELN "};" TO g_HFILE
WRITELN "struct ", g_RECORDNAME$, " ", g_RECORDVAR$, " = { } ;" TO g_HFILE
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 IS 0 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: invalid END SELECT at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
WRITELN "}" TO g_CFILE
g_SELECTVAR$[g_SELECTVAR_CTR] = ""
g_IN_CASE[g_SELECTVAR_CTR] = 0
g_CASE_FALL$ = ""
DECR g_SELECTVAR_CTR
END IF
DEFAULT
WRITELN "exit(", element$[2], ");" TO g_CFILE
END SELECT
ELSE
WRITELN "exit(EXIT_SUCCESS);" TO g_CFILE
END IF
CASE "SUB"
Handle_SubFunc(MID$(statement$, INSTR(statement$, "SUB") + 3))
CASE "ENDSUB"
Handle_Endsub
CASE "ENDWITH"
g_WITHVAR$ = ""
CASE "ENDSELECT"
IF g_SELECTVAR_CTR IS 0 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: invalid END SELECT at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty CALL at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
exp$ = MID$(statement$, INSTR(statement$, "CALL ") + 5)
IF INSTR(statement$, " TO ") THEN
IF INSTR(MID$(exp$, INSTR(exp$, " TO ") + 4), g_STRINGSIGN$) THEN
WRITELN MID$(exp$, INSTR(exp$, " TO ") + 4), " = realloc(", MID$(exp$, INSTR(exp$, " TO ") + 4), ", (strlen(", MID$(exp$, 1, INSTR(exp$, " TO ") - 1), ")+1)*sizeof(char));" TO g_CFILE
WRITELN "strcpy(", MID$(exp$, INSTR(exp$, " TO ") + 4), "," TO g_CFILE
ELSE
WRITELN MID$(exp$, INSTR(exp$, " TO") + 3), "=" TO g_CFILE
END IF
IF INSTR(exp$, "(") THEN
WRITELN MID$(exp$, 1, INSTR(exp$, " TO ") - 1) TO g_CFILE
ELSE
WRITELN MID$(exp$, 1, INSTR(exp$, " TO ") - 1), "()" TO g_CFILE
END IF
IF INSTR(MID$(exp$, INSTR(exp$, " TO ") + 4), g_STRINGSIGN$) THEN
WRITELN ");" TO g_CFILE
ELSE
WRITELN ";" TO g_CFILE
END IF
ELSE
IF INSTR(exp$, "(") THEN
WRITELN exp$, ";" TO g_CFILE
ELSE
WRITELN exp$, "();" TO g_CFILE
END IF
END IF
END IF
CASE "FUNCTION"
Handle_SubFunc(MID$(statement$, INSTR(statement$, "FUNCTION") + 8))
CASE "ENDFUNCTION"
Handle_Endfunction
CASE "RETURN"
Handle_Return(MID$(statement$, INSTR(statement$, "RETURN") + 6))
CASE "IMPORT"
Handle_Import(MID$(statement$, INSTR(statement$, "IMPORT") + 6))
CASE "DECLARE"
Handle_Declare(MID$(statement$, INSTR(statement$, "DECLARE") + 7))
CASE "GLOBAL"
Handle_Declare(MID$(statement$, INSTR(statement$, "GLOBAL") + 6))
CASE "LOCAL"
Handle_Local(MID$(statement$, INSTR(statement$, "LOCAL") + 5))
CASE "DATA"
Handle_Data(MID$(statement$, INSTR(statement$, "DATA") + 4))
CASE "RESTORE"
WRITELN "if(__b2c__floatarray_ptr > 0) __b2c__floatarray_ptr = 0;" TO g_CFILE
WRITELN "if(__b2c__stringarray_ptr > 0) __b2c__stringarray_ptr = 0;" TO g_CFILE
CASE "READ"
Handle_Read(CHOP$(MID$(statement$, INSTR(statement$, "READ") + 4)))
CASE "PUSH"
Handle_Push(CHOP$(MID$(statement$, INSTR(statement$, "PUSH") + 4)))
CASE "PULL"
Handle_Pull(CHOP$(MID$(statement$, INSTR(statement$, "PULL") + 4)))
CASE "SEED"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty DATA at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
WRITELN "srandom((unsigned int)", element$[2], ");" TO g_CFILE
END IF
CASE "DEF"
Handle_Deffn(CHOP$(MID$(statement$, INSTR(statement$, "DEF") + 3)))
CASE "CONST"
Handle_Const(CHOP$(MID$(statement$, INSTR(statement$, "CONST") + 5)))
CASE "INCLUDE"
' Get rid of doublequotes if they are there
inc$ = REPLACE$((CHOP$(MID$(statement$, INSTR(statement$, " ") + 1))), CHR$(34), "")
' See if there are arguments
IF INSTR(inc$, ",") THEN
SPLIT MID$(inc$, INSTR(inc$, ",")+1) BY "," TO element$ SIZE size
FOR i = 1 TO size
element$[i] = REPLACE$(element$[i], g_STRINGSIGN$, "")
NEXT
inc$ = MID$(inc$, 1, INSTR(inc$, ",")-1)
ELSE
to_parse = 2
END IF
' Check argument
IF NOT(FILEEXISTS(inc$)) OR dim EQ 1 OR (FILETYPE(inc$) != 1 AND FILETYPE(inc$) != 6) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing file '", inc$, "' for INCLUDE at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
' Check if the C Preprocessor needs to run
IF ISTRUE(g_CPP) THEN
IF ISTRUE(LEN(EXEC$("which cpp 2>/dev/null"))) THEN
SYSTEM CONCAT$("cpp -P -w ", inc$, " ", inc$, ".cpp")
newfeed$ = CONCAT$(inc$, ".cpp")
g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", inc$, ".cpp")
ELSE
PRINT "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)
' Get the amount of lines
totallines = Count_Lines(newfeed$)
exp$ = gtk_window_get_title(g_Progress)
gtk_window_set_title(g_Progress, CONCAT$("Converting '", MID$(newfeed$, INSTRREV(newfeed$, "/")+1), "'")):SYNC
OPEN newfeed$ FOR READING AS newfile
WHILE NOT(ENDFILE(newfile)) DO
READLN txt$ FROM newfile
' See if we need to enable flag
IF size > 0 THEN
FOR i = 1 TO size
IF ( to_parse = 0 AND REGEX(CHOP$(MID$(txt$, INSTR(txt$, " "))), CONCAT$("^", CHOP$(element$[i]))) AND REGEX(txt$, "SUB|FUNCTION") ) OR REGEX(txt$, "INCLUDE$") THEN
to_parse = 1
BREAK
END IF
NEXT
END IF
' Line is not empty?
IF NOT(ENDFILE(newfile)) AND LEN(txt$) > 0 AND to_parse > 0 THEN
' Update progressbar
gtk_progress_bar_set_text(g_Progressbar, CONCAT$("Parsing line ", STR$( g_COUNTER)) )
gtk_progress_bar_set_fraction(g_Progressbar, (double)(g_COUNTER-1)/totallines):SYNC
IF EQUAL(RIGHT$(txt$, 2), CONCAT$(" ", CHR$(92))) AND NOT(EQUAL(LEFT$(txt$, 3), "REM")) AND NOT(EQUAL(LEFT$(txt$, 1), CHR$(39))) THEN
total$ = CONCAT$(total$, LEFT$(txt$, LEN(txt$)-2))
ELSE
WRITELN "/* noparse ", newfeed$, " BACON LINE ", g_COUNTER, " */" TO g_HFILE
WRITELN "/* noparse ", newfeed$, " BACON LINE ", g_COUNTER, " */" TO g_CFILE
total$ = CHOP$(CONCAT$(total$, txt$))
IF NOT(EQUAL(LEFT$(total$, 3), "REM")) AND NOT(EQUAL( LEFT$(total$, 1), CHR$(39) )) THEN
CALL Tokenize(total$)
END IF
LET total$ = ""
END IF
IF g_PARSE_STATUS THEN BREAK
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 title of progress bar
gtk_window_set_title(g_Progress, exp$):SYNC
' 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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty POKE at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
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; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} }" TO g_CFILE
WRITELN "*(", g_OPTION_MEMTYPE$, "*)(", MID$(exp$, 1, INSTR(exp$, ",")-1), ") = ( ", g_OPTION_MEMTYPE$, ")", MID$(exp$, INSTR(exp$, ",")+1), ";" TO g_CFILE
END IF
CASE "RESIZE"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty RESIZE at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
' Resolve this with C macro because of casting to (char)
exp$ = MID$(statement$, INSTR(statement$, "RESIZE") + 6)
WRITELN MID$(exp$, 1, INSTR(exp$, ",") - 1), " = (long)RESIZE(", exp$, ");" TO g_CFILE
END IF
CASE "COPY"
Handle_Copy(MID$(statement$, INSTR(statement$, "COPY") + 4))
CASE "DELETE"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty DELETE at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
' Translate to C function
IF EQUAL(element$[2], "FILE") THEN
WRITELN "if (unlink(", MID$(statement$, INSTR(statement$, " FILE ") + 6), ")==-1){if(!__b2c__trap){ERROR = 7;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
ELIF EQUAL(element$[2], "DIRECTORY") THEN
WRITELN "if (rmdir(", MID$(statement$, INSTR(statement$, " DIRECTORY ") + 11), ") == -1){if(!__b2c__trap){ERROR = 20;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
ELSE
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: erronuous argument for DELETE at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
END IF
CASE "RENAME"
Handle_Rename(MID$(statement$, INSTR(statement$, "RENAME") + 6))
CASE "MAKEDIR"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty MAKEDIR at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
' Translate to C function
WRITELN "if(__b2c__makedir(", MID$(statement$, INSTR(statement$, "MAKEDIR") + 7), ") != 0){if(!__b2c__trap){ERROR = 21;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
END IF
CASE "CHANGEDIR"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty CHANGEDIR at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
' Translate to C function
WRITELN "if(chdir(", MID$(statement$, INSTR(statement$, "CHANGEDIR") + 9), ") == -1){if(!__b2c__trap) {ERROR = 22;if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
END IF
CASE "FREE"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty FREE at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
' Translate to C function
IF REGEX(element$[2], "\\(.*\\)") THEN
exp$ = MID$(element$[2], INSTR(element$[2], " ")+1)
IF INSTR(exp$, g_STRINGSIGN$) THEN
WRITELN "if(__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1)," != NULL) {free(__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1), "->value);" TO g_CFILE
WRITELN " __b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1), "->value = NULL; __b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "__del(", MID$(element$[2], INSTR(element$[2], "(")+1), "; }" TO g_CFILE
ELSE
WRITELN "if(__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1)," != NULL) {__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "_exist(", MID$(element$[2], INSTR(element$[2], "(")+1), "->value = 0;" TO g_CFILE
WRITELN "__b2c__", MID$(exp$, 1, INSTR(exp$, "(")-1), "__del(", MID$(element$[2], INSTR(element$[2], "(")+1), ";}" TO g_CFILE
ENDIF
ELSE
WRITELN "if(!__b2c__trap){if(__b2c__memory__check((char *)", element$[2], "))" TO g_CFILE
WRITELN "{ERROR=1; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} } free((void*)", element$[2], ");" TO g_CFILE
END IF
END IF
CASE "GOTO"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty GOTO at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
' Translate to C label
WRITELN "goto ", element$[2], ";" TO g_CFILE
END IF
CASE "GOSUB"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty GOSUB at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
' Translate to C label
WRITELN "__b2c__gosub_buffer_ptr++; if (__b2c__gosub_buffer_ptr >= ", g_MAX_RBUFFERS, ") {ERROR=31; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";}" TO g_CFILE
WRITELN "if(!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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty LABEL at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
' Translate to C label
WRITELN element$[2], ":" TO g_CFILE
WRITELN ";" TO g_CFILE
END IF
CASE "TRAP"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty TRAP at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
IF EQUAL(element$[2], "SYSTEM") THEN
WRITELN "/* Error catching is enabled */" TO g_CFILE
WRITELN "__b2c__trap = 1;" TO g_CFILE
WRITELN "signal(SIGILL, __b2c__catch_signal);" TO g_CFILE
WRITELN "signal(SIGABRT, __b2c__catch_signal);" TO g_CFILE
WRITELN "signal(SIGFPE, __b2c__catch_signal);" TO g_CFILE
WRITELN "signal(SIGSEGV, __b2c__catch_signal);" TO g_CFILE
ELIF EQUAL(element$[2], "LOCAL") THEN
WRITELN "/* Error catching is disabled */" TO g_CFILE
WRITELN "__b2c__trap = 0;" TO g_CFILE
WRITELN "signal(SIGILL, SIG_DFL);" TO g_CFILE
WRITELN "signal(SIGABRT, SIG_DFL);" TO g_CFILE
WRITELN "signal(SIGFPE, SIG_DFL);" TO g_CFILE
WRITELN "signal(SIGSEGV, SIG_DFL);" TO g_CFILE
ELSE
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: invalid argument for TRAP at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
END IF
CASE "CATCH"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty CATCH at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELIF EQUAL(element$[2], "GOTO") THEN
WRITELN "__b2c__catch_set = 1;" TO g_CFILE
g_CATCHGOTO$ = element$[3]
ELIF EQUAL(element$[2], "RESET") THEN
WRITELN "__b2c__catch_set = 0;" TO g_CFILE
g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT"
ELSE
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: CATCH without GOTO or RESET at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty RECORD at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELIF ISTRUE(LEN(g_RECORDNAME$)) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: cannot define a record within a record!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
' Translate to C typedef struct
IF ISTRUE(LEN(g_FUNCNAME$)) THEN
g_RECORDNAME$ = CONCAT$("RECORD_", g_FUNCNAME$, "_", STR$(g_COUNTER))
WRITELN "struct ", g_RECORDNAME$, "{" TO g_CFILE
ELSE
g_RECORDNAME$ = CONCAT$("RECORD_", STR$(g_COUNTER))
WRITELN "struct ", g_RECORDNAME$, "{" TO g_HFILE
END IF
g_RECORDVAR$ = element$[2]
END IF
CASE "WITH"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty WITH at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELIF ISTRUE(LEN(g_RECORDNAME$)) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: cannot define a WITH within a WITH!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
g_WITHVAR$ = element$[2]
END IF
CASE "SPLIT"
Handle_Split(MID$(statement$, INSTR(statement$, "SPLIT") + 5))
CASE "SELECT"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty SELECT at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty CASE at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
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 EQUAL(RIGHT$(statement$, 1), ";") THEN
exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4)
g_CASE_FALL$ = CONCAT$("|| !strcmp(", g_SELECTVAR$[g_SELECTVAR_CTR], ", ", LEFT$(exp$, LEN(exp$)-1), ") ", g_CASE_FALL$)
ELSE
WRITELN "} else if (!strcmp(", g_SELECTVAR$[g_SELECTVAR_CTR], ", ", MID$(statement$, INSTR(statement$, "CASE") + 4), ") ", g_CASE_FALL$, "){" TO g_CFILE
g_CASE_FALL$ = ""
END IF
ELSE
IF EQUAL(RIGHT$(statement$, 1), ";") THEN
exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4)
g_CASE_FALL$ = CONCAT$("|| ", g_SELECTVAR$[g_SELECTVAR_CTR], " == (", LEFT$(exp$, LEN(exp$)-1), ")", g_CASE_FALL$)
ELSE
WRITELN "} else if (", g_SELECTVAR$[g_SELECTVAR_CTR], " == (", MID$(statement$, INSTR(statement$, "CASE") + 4), ") ", g_CASE_FALL$, "){" TO g_CFILE
g_CASE_FALL$ = ""
END IF
END IF
ELSE
IF INSTR(MID$(g_SELECTVAR$[g_SELECTVAR_CTR], 1, size), g_STRINGSIGN$) THEN
IF EQUAL(RIGHT$(statement$, 1), ";") THEN
exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4)
g_CASE_FALL$ = CONCAT$("|| !strcmp(", g_SELECTVAR$[g_SELECTVAR_CTR], ", ", LEFT$(exp$, LEN(exp$)-1), ") ", g_CASE_FALL$)
ELSE
WRITELN "if (!strcmp(", g_SELECTVAR$[g_SELECTVAR_CTR], ", ", MID$(statement$, INSTR(statement$, "CASE") + 4),") ", g_CASE_FALL$, "){" TO g_CFILE
g_IN_CASE[g_SELECTVAR_CTR] = 1
g_CASE_FALL$ = ""
END IF
ELSE
IF EQUAL(RIGHT$(statement$, 1), ";") THEN
exp$ = MID$(statement$, INSTR(statement$, "CASE") + 4)
g_CASE_FALL$ = CONCAT$("|| ", g_SELECTVAR$[g_SELECTVAR_CTR], " == (", LEFT$(exp$, LEN(exp$)-1), ")", g_CASE_FALL$)
ELSE
WRITELN "if (", g_SELECTVAR$[g_SELECTVAR_CTR], " == (", MID$(statement$, INSTR(statement$, "CASE") + 4), ") ", g_CASE_FALL$, "){" TO g_CFILE
g_IN_CASE[g_SELECTVAR_CTR] = 1
g_CASE_FALL$ = ""
END IF
END IF
END IF
END IF
CASE "DEFAULT"
IF ISTRUE(g_IN_CASE[g_SELECTVAR_CTR]) THEN
WRITELN "} else {" TO g_CFILE
ELSE
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: cannot use DEFAULT without previous CASE at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
g_IN_CASE[g_SELECTVAR_CTR] = 0
g_CASE_FALL$ = ""
CASE "SETENVIRON"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty SETENVIRON at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
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
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty TRACE at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
IF EQUAL(element$[2], "ON") THEN g_TRACE = 1
ELIF EQUAL(element$[2], "OFF") THEN g_TRACE =0
ENDIF
CASE "OPTION"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty OPTION at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
IF EQUAL(element$[2], "BASE") AND dim IS 3 THEN
IF REGEX(element$[3], "[0-9]") THEN
g_OPTION_BASE = VAL(element$[3])
ELSE
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: invalid argument to OPTION BASE at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
ELIF EQUAL(element$[2], "COMPARE") AND dim IS 3 THEN
IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
WRITELN "__b2c__option_compare = ", element$[3], ";" TO g_CFILE
ELSE
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: invalid argument to OPTION COMPARE at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
ELIF EQUAL(element$[2], "SOCKET") AND dim IS 3 THEN
IF REGEX(element$[3], "[0-9]") THEN
g_OPTION_SOCKET = VAL(element$[3])
ELSE
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: invalid argument to OPTION SOCKET at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
ELIF EQUAL(element$[2], "MEMSTREAM") AND dim IS 3 THEN
IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
WRITELN "__b2c__option_memstream = ", element$[3], ";" TO g_CFILE
ELSE
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: invalid argument to OPTION MEMSTREAM at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
ELIF EQUAL(element$[2], "MEMTYPE") AND dim IS 3 THEN
IF REGEX(statement$, ".*short.*") THEN
WRITELN "__b2c__memtype = 2;" TO g_CFILE
g_OPTION_MEMTYPE$ = "short"
ELIF REGEX(statement$, ".*int.*") THEN
WRITELN "__b2c__memtype = 3;" TO g_CFILE
g_OPTION_MEMTYPE$ = "int"
ELIF REGEX(statement$, ".*long.*|.*NUMBER.*") THEN
WRITELN "__b2c__memtype = 4;" TO g_CFILE
g_OPTION_MEMTYPE$ = "long"
ELIF REGEX(statement$, ".*float.*") THEN
WRITELN "__b2c__memtype = 5;" TO g_CFILE
g_OPTION_MEMTYPE$ = "float"
ELIF REGEX(statement$, ".*double.*|.*FLOATING.*") THEN
WRITELN "__b2c__memtype = 6;" TO g_CFILE
g_OPTION_MEMTYPE$ = "double"
ELIF REGEX(statement$, ".*void.*|.*char\\*.*|.*STRING.*") THEN
WRITELN "__b2c__memtype = 7;" TO g_CFILE
g_OPTION_MEMTYPE$ = "char*"
ELIF REGEX(statement$, ".*char.*") THEN
WRITELN "__b2c__memtype = 1;" TO g_CFILE
g_OPTION_MEMTYPE$ = "char"
ELSE
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: invalid argument to OPTION MEMTYPE at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
ELIF EQUAL(element$[2], "COLLAPSE") AND dim IS 3 THEN
IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
WRITELN "__b2c__collapse = ", element$[3], ";" TO g_CFILE
ELSE
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: invalid argument to OPTION COLLAPSE at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
ELIF EQUAL(element$[2], "STARTPOINT") AND dim IS 3 THEN
IF REGEX(element$[3], "[0-1]|TRUE|FALSE") THEN
WRITELN "__b2c__option_startpoint = ", element$[3], ";" TO g_CFILE
ELSE
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: invalid argument to OPTION STARTPOINT at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
ELIF EQUAL(element$[2], "INTERNATIONAL") AND dim IS 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){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
WRITELN "if (textdomain(\"", LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".")-1), "\")==NULL){if(!__b2c__trap){ERROR = 6; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
ELSE
PRINT NL$, "ERROR: invalid argument to OPTION INTERNATIONAL at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
END 1
END IF
ELIF EQUAL(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
DEFAULT
PRINT NL$, "ERROR: invalid argument to OPTION NETWORK at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
END 1
END SELECT
ELSE
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: argument to OPTION at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "' not recognized!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
END IF
CASE "PROTO"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty PROTO at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
exp$ = MID$(REPLACE$(statement$, CHR$(34), ""), INSTR(statement$, "PROTO") + 5)
' Check if ALIAS is there
IF INSTR(exp$, " ALIAS ") THEN
WRITELN "#define ", MID$(exp$, INSTR(exp$, " ALIAS ") + 7), " ", MID$(exp$, 1, INSTR(exp$, " ALIAS ")) TO g_HFILE
g_IMPORTED$ = CONCAT$(MID$(exp$, INSTR(exp$, " ALIAS ") + 7), " ", g_IMPORTED$)
g_IMPORTED$ = CONCAT$(MID$(exp$, 1, INSTR(exp$, " ALIAS ")), " ", g_IMPORTED$)
ELSE
g_IMPORTED$ = CONCAT$(REPLACE$(exp$, ",", " "), " ", g_IMPORTED$)
END IF
END IF
CASE "INCR"
' Check argument
IF dim EQ 1 THEN
PRINT NL$, "ERROR: empty INCR at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
END 1
ELSE
' Walk through commas
SPLIT CHOP$(MID$(statement$, INSTR(statement$, "INCR") + 4)) BY "," TO sym$ SIZE dim
IF dim IS 1 THEN
exp$ = "1"
ELSE
exp$ = CHOP$(MID$(statement$, INSTR(statement$, ",") + 1))
END IF
' Check if there is associative array assignment
IF REGEX(sym$[1], "\\(.*\\)$") THEN
lft$ = LEFT$(sym$[1], INSTR(sym$[1], "(") - 1)
str$ = MID$(sym$[1], INSTR(sym$[1], "(") + 1)
WRITELN "if(__b2c__", lft$, "_exist (", str$, " == NULL) __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
WRITELN "__b2c__", lft$, "_exist(", str$, "->value = ", sym$[1], " + (", exp$, ");" TO g_CFILE
' Check for relations
Relate_Recurse(lft$, str$, exp$, -1)
ELSE
WRITELN sym$[1], " = ", sym$[1], " + (", exp$, ");" TO g_CFILE
END IF
END IF
CASE "DECR"
' Check argument
IF dim EQ 1 THEN
PRINT NL$, "ERROR: empty DECR at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
END 1
ELSE
' Walk through commas
SPLIT CHOP$(MID$(statement$, INSTR(statement$, "DECR") + 4)) BY "," TO sym$ SIZE dim
IF dim IS 1 THEN
exp$ = "1"
ELSE
exp$ = CHOP$(MID$(statement$, INSTR(statement$, ",") + 1))
END IF
' Check if there is associative array assignment
IF REGEX(sym$[1], "\\(.*\\)$") THEN
lft$ = LEFT$(sym$[1], INSTR(sym$[1], "(") - 1)
str$ = MID$(sym$[1], INSTR(sym$[1], "(") + 1)
WRITELN "if(__b2c__", lft$, "_exist (", str$, " == NULL) __b2c__", lft$, "__add(", str$, ";" TO g_CFILE
WRITELN "__b2c__", lft$, "_exist(", str$, "->value = ", sym$[1], " - (", exp$, ");" TO g_CFILE
' Check for relations
Relate_Recurse(lft$, str$, exp$, -1)
ELSE
WRITELN sym$[1], " = ", sym$[1], " - (", exp$, ");" TO g_CFILE
END IF
END IF
CASE "ALARM"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty ALARM at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
' Walk through commas
SPLIT CHOP$(MID$(statement$, INSTR(statement$, "ALARM") + 5)) BY "," TO sym$ SIZE dim
IF dim IS 2 THEN
WRITELN "signal(SIGALRM, (void*)", sym$[1], ");" TO g_CFILE
WRITELN "alarm(", sym$[2], ");" TO g_CFILE
ELSE
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: missing argument in ALARM at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
END IF
END IF
CASE "CURSOR"
' Check argument
IF dim EQ 1 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: empty CURSOR at line ", STR$(g_COUNTER), " in file '", g_CURFILE$, "'!"), g_COUNTER)
g_PARSE_STATUS = 1:GOTO End_Func
ELSE
IF EQUAL(element$[2], "ON") THEN WRITELN "fprintf(stdout,\"\\033[?25h\"); fflush(stdout);" TO g_CFILE
ELIF EQUAL(element$[2], "OFF") THEN WRITELN "fprintf(stdout,\"\\033[?25l\"); fflush(stdout);" TO g_CFILE
ENDIF
CASE "ALIAS"
Handle_Alias(CHOP$(MID$(statement$, INSTR(statement$, "ALIAS") + 5)))
CASE "LOOKUP"
Handle_Lookup(CHOP$(MID$(statement$, INSTR(statement$, "LOOKUP") + 6)))
CASE "RELATE"
Handle_Relate(CHOP$(MID$(statement$, INSTR(statement$, "RELATE") + 6)))
CASE "TEXTDOMAIN"
' Check argument
IF dim EQ 1 THEN
PRINT NL$, "ERROR: empty TEXTDOMAIN at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
END 1
ELSE
' Walk through commas
SPLIT CHOP$(MID$(statement$, INSTR(statement$, "TEXTDOMAIN") + 10)) BY "," TO sym$ SIZE dim
IF dim IS 2 THEN
WRITELN "if(bindtextdomain(", sym$[1], ",", sym$[2], ")==NULL){if(!__b2c__trap){ERROR = 6; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
WRITELN "if(textdomain(", sym$[1], ")==NULL){if(!__b2c__trap){ERROR = 6; if(!__b2c__catch_set){fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} if(!setjmp(__b2c__jump)) goto ", g_CATCHGOTO$, ";} }" TO g_CFILE
ELSE
PRINT NL$, "ERROR: missing argument in TEXTDOMAIN at line ", g_COUNTER, " in file '", g_CURFILE$, "'!"
END 1
END IF
END IF
CASE "REDIM"
Handle_Redim(CHOP$(MID$(statement$, INSTR(statement$, "REDIM") + 5)))
DEFAULT
' Check on imported symbols first
IF INSTR(element$[1], "(") THEN element$[1] = LEFT$(element$[1], INSTR(element$[1], "(") - 1)
SPLIT CHOP$(g_IMPORTED$) BY " " TO sym$ SIZE dim
found = FALSE
FOR i = 1 TO dim
IF EQUAL(sym$[i], element$[1]) THEN
IF REGEX(statement$, "\\(.*\\)") THEN WRITELN statement$, ";" TO g_CFILE
ELSE WRITELN statement$, "();" TO g_CFILE
found = TRUE
BREAK
END IF
NEXT
' Not an imported symbol? Check if assignment
IF NOT(found) THEN Handle_Let(statement$)
END SELECT
END IF
END IF
LABEL End_Func
END SUB
'----------------------------------------------------------------------------------------------
SUB Tokenize (STRING current$)
LOCAL dim, i, is_string, is_escaped
LOCAL token$
' Initialize parser
is_string = FALSE
is_escaped = FALSE
token$ = ""
' See if there are colons
FOR i = 1 TO LEN(current$)
IF EQUAL(MID$(current$, i, 5), "INTL$") THEN
IF ISFALSE(is_string) THEN
token$ = CONCAT$(token$, "gettext")
INCR i, 5
END IF
ELIF EQUAL(MID$(current$, i, 5), "NNTL$") THEN
IF ISFALSE(is_string) THEN
token$ = CONCAT$(token$, "ngettext")
INCR i, 5
END IF
END IF
SELECT MID$(current$, i, 1)
' Separator
CASE ":"
IF ISFALSE(is_string) THEN
token$ = CONCAT$(token$, CHR$(10))
ELSE
token$ = CONCAT$(token$, ":")
END IF
' String symbol
CASE "$"
IF ISFALSE(is_string) OR REGEX(current$, "IMPORT.*FROM.*TYPE.*") THEN
token$ = CONCAT$(token$, g_STRINGSIGN$)
is_escaped = FALSE
ELSE
token$ = CONCAT$(token$, "$")
END IF
' Escape symbol
CASE CHR$(92)
token$ = CONCAT$(token$, CHR$(92))
is_escaped = NOT(is_escaped)
' Quote symbol
CASE CHR$(34)
token$ = CONCAT$(token$, CHR$(34))
IF ISFALSE(is_escaped) THEN is_string = NOT(is_string)
is_escaped = FALSE
DEFAULT
token$ = CONCAT$(token$, MID$(current$, i, 1))
is_escaped = FALSE
END SELECT
NEXT
' Split into separate statements
SPLIT token$ BY CHR$(10) TO element$ SIZE dim
' Start parsing
FOR i = 1 TO dim
Parse_Line(CHOP$(element$[i]))
NEXT
END SUB
'----------------------------------------------------------------------------------------------
FUNCTION Parse_Equation$(STRING current$)
LOCAL dim, i, j, is_string, is_escaped, is_equation, opctr
LOCAL token$, term$, eq$, total$, type$
LOCAL logop$[32]
' Initialize parser
is_string = FALSE
is_escaped = FALSE
opctr = 1
' First split into separate chunks OR/AND
FOR i = 1 TO LEN(current$)
IF EQUAL(MID$(current$, i, 5), " AND ") THEN
IF ISFALSE(is_string) THEN
token$ = CONCAT$(token$, CHR$(10))
logop$[opctr] = " AND "
INCR opctr : INCR i, 4
ELSE
token$ = CONCAT$(token$, " ")
END IF
ELIF EQUAL(MID$(current$, i, 4), " OR ") THEN
IF ISFALSE(is_string) THEN
token$ = CONCAT$(token$, CHR$(10))
logop$[opctr] = " OR "
INCR opctr : INCR i, 3
ELSE
token$ = CONCAT$(token$, " ")
END IF
ELIF EQUAL(MID$(current$, i, 1), CHR$(92)) THEN
token$ = CONCAT$(token$, CHR$(92))
is_escaped = NOT(is_escaped)
ELIF EQUAL(MID$(current$, i, 1), CHR$(34)) THEN
token$ = CONCAT$(token$, CHR$(34))
IF ISFALSE(is_escaped) THEN is_string = NOT(is_string)
is_escaped = FALSE
ELSE
token$ = CONCAT$(token$, MID$(current$, i, 1))
is_escaped = FALSE
END IF
NEXT
logop$[opctr] = ""
opctr = 1
' Split into separate chunks
SPLIT token$ BY CHR$(10) TO element$ SIZE dim
' Start parsing
FOR j = 1 TO dim
' Initialize for this chunk
eq$ = "!"
token$ = ""
is_equation = 0
is_string = 0
is_escaped = 0
' Check if this is a string
IF INSTR(element$[j], "(") THEN
type$ = MID$(element$[j], 1, INSTR(element$[j], "("))
ELSE
type$ = element$[j]
END IF
' See if there are equal signs
FOR i = 1 TO LEN(element$[j])
SELECT MID$(element$[j], i, 1)
' Separator
CASE "="
IF ISFALSE(is_string) THEN
IF INSTR(type$, g_STRINGSIGN$) OR INSTR(type$, CHR$(34)) THEN
term$ = token$
token$ = ""
ELIF NOT(is_equation) THEN
token$ = CONCAT$(token$, "==")
ELSE
token$ = CONCAT$(token$, "=")
is_equation = 0
END IF
ELSE
token$ = CONCAT$(token$, "=")
END IF
' Negation
CASE "!"
IF ISFALSE(is_string) THEN
IF INSTR(type$, g_STRINGSIGN$) OR INSTR(type$, CHR$(34)) THEN
eq$ = ""
ELIF NOT(is_equation) THEN
token$ = CONCAT$(token$, "!=")
INCR i
ELSE
token$ = CONCAT$(token$, "!")
is_equation = 0
END IF
ELSE
token$ = CONCAT$(token$, "!")
END IF
' Comparison symbols
CASE "<"
token$ = CONCAT$(token$, "<")
is_equation = 1
CASE ">"
token$ = CONCAT$(token$, ">")
is_equation = 1
CASE "#"
token$ = CONCAT$(token$, "#")
is_equation = 1
' Escape symbol
CASE CHR$(92)
token$ = CONCAT$(token$, CHR$(92))
is_escaped = NOT(is_escaped)
' Quote symbol
CASE CHR$(34)
token$ = CONCAT$(token$, CHR$(34))
IF ISFALSE(is_escaped) THEN is_string = NOT(is_string)
is_escaped = FALSE
DEFAULT
token$ = CONCAT$(token$, MID$(element$[j], i, 1))
is_escaped = FALSE
END SELECT
NEXT
' Construct string equation
IF INSTR(type$, g_STRINGSIGN$) OR INSTR(type$, CHR$(34)) THEN token$ = CONCAT$("((__b2c__option_compare == 0) ? ", eq$, "strcmp(", term$, ",", token$, ") : ", eq$, "strcasecmp(", term$, ",", token$, "))")
total$ = CONCAT$(total$, token$)
' Restore logical operator
total$ = CONCAT$(total$, logop$[opctr])
INCR opctr
NEXT
RETURN total$
END FUNCTION
'------------------------------------------------------------------------------------------------------------
SUB Convert_Source(NUMBER widget, NUMBER dialog)
LOCAL setting$, LDFLAGS$, total$, line$, FEED$, lang$
LOCAL i, size, totallines, COUNTER
' Link flags
IF INSTR(OS$, "OSF1") OR INSTR(OS$, "BSD") THEN LDFLAGS$ = "-lm"
ELSE LDFLAGS$ = "-lm -ldl"
' Solaris
IF INSTR(OS$, "SunOS" ) THEN LDFLAGS$ = CONCAT$(LDFLAGS$, " -lnsl -lsocket")
' Variable to skip rest of function if there is an
LET g_PARSE_STATUS = 0
' Default BACON settings
LET g_MAX_DIGITS = 32
' Maximum of internal buffers needed for string processing
LET g_MAX_BUFFERS = 32
' This is the size for static buffers like fgets, read etc.
LET g_BUFFER_SIZE = 512
' Maximum RETURN buffers
LET g_MAX_RBUFFERS = 32
LET g_NO_COMPILE = 0
LET g_TMP_PRESERVE = 0
LET g_USE_C = 0
LET g_MAX_BACKLOG = 4
LET g_CPP = 0
LET g_XGETTEXT = 0
g_TEMPDIR$ = "."
g_CCNAME$ = "cc"
g_CCFLAGS$ = ""
g_INCFILES$ = ""
g_INCLUDE_FILES$ = ""
LET g_TRACE = 0
LET g_OPTION_BASE = 0
LET g_OPTION_SOCKET = 5
LET g_OPTION_MEMTYPE$ = "char"
LET g_IF_PARSE = 0
' Some global declarations
g_CURFILE$ = ""
g_FUNCNAME$ = ""
g_FUNCTYPE$ = ""
g_PROTOTYPE$ = ""
g_TMP_FILES$ = ""
g_LOCALSTRINGS$ = ""
g_STRINGARRAYS$ = ""
g_STRINGARGS$ = ""
g_BINEXT$ = ""
g_RECORDCACHE$ = ""
LET g_LOOPCTR = 0
g_ERRORTXT$ = ""
' Always create a final label
g_CATCHGOTO$ = "__B2C__PROGRAM__EXIT"
' Records
g_RECORDNAME$ = ""
g_RECORDVAR$ = ""
g_WITHVAR$ = ""
g_RECORDEND_BODY$ = ""
g_RECORDEND_HEADER$ = ""
' Socket defaults
g_SOCKTYPE$ = "SOCK_STREAM"
g_NETWORKTYPE$ = "TCP"
g_MULTICAST_TTL = 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
' Determine options
g_CCNAME$ = gtk_entry_get_text(g_Compiler_entry)
' Include option
setting$ = gtk_entry_get_text(g_Inc_entry)
SPLIT setting$ BY " " TO args$ SIZE size
FOR i = 1 TO size
IF NOT(FILEEXISTS(args$[i])) AND NOT(FILEEXISTS(CONCAT$("/usr/include/", args$[i]))) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "ERROR: included C header file from -i option not found!", -1)
GOTO End_Func
END IF
IF LEN(args$[i]) > 0 THEN
IF NOT(FILEEXISTS(CONCAT$("/usr/include/", args$[i]))) THEN
g_INCFILES$ = CONCAT$("#include \"", args$[i], "\"", NL$, g_INCFILES$)
ELSE
g_INCFILES$ = CONCAT$("#include <", args$[i], ">", NL$, g_INCFILES$)
END IF
END IF
NEXT
' Library flags
setting$ = gtk_entry_get_text(g_Flags_entry)
SPLIT setting$ BY " " TO args$ SIZE size
FOR i = 1 TO size
LDFLAGS$ = CONCAT$(LDFLAGS$, " -l", args$[i])
NEXT
' Temporary directory
g_TEMPDIR$ = gtk_entry_get_text(g_Tmpdir_entry)
IF NOT(FILEEXISTS(g_TEMPDIR$)) THEN MAKEDIR g_TEMPDIR$
IF NOT(FILEEXISTS(g_TEMPDIR$)) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("ERROR: temporary directory '", g_TEMPDIR$, "' does not exist!"), -1)
GOTO End_Func
END IF
' Compiler flags
setting$ = gtk_entry_get_text(g_Options_entry)
SPLIT setting$ BY " " TO args$ SIZE size
FOR i = 1 TO size
IF LEN(args$[i]) > 0 THEN g_CCFLAGS$ = CONCAT$(g_CCFLAGS$, " ", args$[i])
NEXT
' Gettext
g_XGETTEXT = gtk_toggle_button_get_active(g_Gettext_check)
' Preserve option
g_TMP_PRESERVE = gtk_toggle_button_get_active(g_Pre_check)
' No compile option
g_NO_COMPILE = gtk_toggle_button_get_active(g_Con_check)
' Invoke C Preprocessor
g_CPP = gtk_toggle_button_get_active(g_Cpp_check)
' Shared library
IF gtk_toggle_button_get_active(g_So_check) THEN
g_CCFLAGS$ = CONCAT$(g_CCFLAGS$, " -shared -rdynamic")
IF INSTR(OS$, "x86_64") THEN g_CCFLAGS$ = CONCAT$(g_CCFLAGS$, " -fPIC")
g_BINEXT$ = ".so"
END IF
IF dialog > 0 THEN
gtk_widget_hide(dialog)
' Make sure file is saved
CALL Save_File
' This is the sourcefile
g_SOURCEFILE$ = nbook[gtk_notebook_get_current_page(g_Notebook)].title$
ELSE
g_SOURCEFILE$ = CONCAT$(g_TEMPDIR$, g_BACONSHELL$)
END IF
IF LEN(g_SOURCEFILE$) IS 0 THEN GOTO End_Func
' Change the working directory
CHANGEDIR MID$(g_SOURCEFILE$, 1, INSTRREV(g_SOURCEFILE$, "/")-1)
' Now create the global filenames where to write to
g_CFILE$ = CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".c")
g_HFILE$ = CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".h")
STRINGARRAYFILE$ = CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".string.h")
FLOATARRAYFILE$ = CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".float.h")
' Check to overwrite
IF FILEEXISTS(g_CFILE$) OR FILEEXISTS(g_HFILE$) THEN
IF FILEEXISTS(g_CFILE$) THEN DELETE FILE g_CFILE$
IF FILEEXISTS(g_HFILE$) THEN DELETE FILE g_HFILE$
IF FILEEXISTS(STRINGARRAYFILE$) THEN DELETE FILE STRINGARRAYFILE$
IF FILEEXISTS(FLOATARRAYFILE$) THEN DELETE FILE FLOATARRAYFILE$
END IF
' Add to total file list
g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_CFILE$)
g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_HFILE$)
g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", STRINGARRAYFILE$)
g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", FLOATARRAYFILE$)
' Create new sourcefile
OPEN g_CFILE$ FOR WRITING AS g_CFILE
' Create basic C file
WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO g_CFILE
WRITELN "#include \"", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".h\"" TO g_CFILE
WRITELN "int main(int argc, const char **argv)" TO g_CFILE
WRITELN "{" TO g_CFILE
WRITELN "/* Default is: system traps signals */" TO g_CFILE
WRITELN "signal(SIGILL, __b2c__catch_signal);" TO g_CFILE
WRITELN "signal(SIGABRT, __b2c__catch_signal);" TO g_CFILE
WRITELN "signal(SIGFPE, __b2c__catch_signal);" TO g_CFILE
WRITELN "signal(SIGSEGV, __b2c__catch_signal);" TO g_CFILE
' Put arguments into reserved variable ARGUMENT
WRITELN "/* Setup the reserved variable 'ARGUMENT' */" TO g_CFILE
WRITELN "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++)" TO g_CFILE
WRITELN "{__b2c__arglen += strlen(argv[__b2c__counter]) + 1;} __b2c__arglen++;" TO g_CFILE
WRITELN "ARGUMENT", g_STRINGSIGN$, " = (char*)calloc(__b2c__arglen, sizeof(char));" TO g_CFILE
WRITELN "for(__b2c__counter=0; __b2c__counter < argc; __b2c__counter++)" TO g_CFILE
WRITELN "{strcat(ARGUMENT", g_STRINGSIGN$, ", argv[__b2c__counter]); if(__b2c__counter != argc - 1) strcat(ARGUMENT", g_STRINGSIGN$, ", \" \");}" TO g_CFILE
WRITELN "/* By default seed random generator */" TO g_CFILE
WRITELN "srandom((unsigned int)time(NULL));" TO g_CFILE
WRITELN "/* Initialize internal stackpointer */" TO g_CFILE
WRITELN "__b2c__typestack = (int*)calloc(1, sizeof(int));" TO g_CFILE
WRITELN "__b2c__stringstack = (char**)realloc(__b2c__stringstack, sizeof(char*)); __b2c__stringstack[0] = calloc(1, sizeof(char));" TO g_CFILE
WRITELN "/* Rest of the program */" TO g_CFILE
' Create new headerfile
OPEN g_HFILE$ FOR WRITING AS g_HFILE
' Create basic H file, functions are converted using macros
WRITELN "/* Created with BaCon ", g_VERSION$, " - (c) Peter van Eerten - GPL v3 */" TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#include " TO g_HFILE
IF INSTR(OS$, "BSD") THEN WRITELN "#include " TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "static jmp_buf __b2c__jump;" TO g_HFILE
WRITELN "static int __b2c__trap = 1;" TO g_HFILE
WRITELN "static int __b2c__catch_set = 0;" TO g_HFILE
WRITELN "static int ERROR = 0;" TO g_HFILE
WRITELN "static int __b2c__option_compare = 0;" TO g_HFILE
WRITELN "static int __b2c__option_memstream = 0;" TO g_HFILE
WRITELN "static int __b2c__option_startpoint = 0;" TO g_HFILE
WRITELN "static int __b2c__memtype = 1;" TO g_HFILE
WRITELN "static int __b2c__collapse = 0;" TO g_HFILE
WRITELN "int __b2c__break_ctr = 0;" TO g_HFILE
WRITELN "int __b2c__break_flag = 0;" TO g_HFILE
WRITELN "int RETVAL = 0;" TO g_HFILE
WRITELN "char __b2c__chop_default[] = \"\\r\\n\\t \";" TO g_HFILE
WRITELN "char VERSION", g_STRINGSIGN$, "[] = \"", g_VERSION$, "\";" TO g_HFILE
' Add user include files
WRITELN "/* User include files */" TO g_HFILE
WRITELN g_INCFILES$ TO g_HFILE
WRITELN "/* READ/DATA include files */" TO g_HFILE
WRITELN "int __b2c__stringarray_ptr = 0;" TO g_HFILE
WRITELN "#include \"", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".string.h\"" TO g_HFILE
WRITELN "int __b2c__floatarray_ptr = 0;" TO g_HFILE
WRITELN "#include \"", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".float.h\"" TO g_HFILE
WRITELN "int __b2c__ctr;" TO g_HFILE
WRITELN "/* Math functions */" TO g_HFILE
WRITELN "extern double round(double __b2c__x);" TO g_HFILE
WRITELN "extern long int lrint(double __b2c__x);" TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#define SQR(__b2c__x) sqrt((double)__b2c__x)" TO g_HFILE
WRITELN "#define POW(__b2c__x, __b2c__y) pow((double)__b2c__x, (double)__b2c__y)" TO g_HFILE
WRITELN "#define SIN(__b2c__x) sin(__b2c__x)" TO g_HFILE
WRITELN "#define COS(__b2c__x) cos(__b2c__x)" TO g_HFILE
WRITELN "#define TAN(__b2c__x) tan(__b2c__x)" TO g_HFILE
WRITELN "#define ATN(__b2c__x) atan(__b2c__x)" TO g_HFILE
WRITELN "#define LOG(__b2c__x) log(__b2c__x)" TO g_HFILE
WRITELN "#define EXP(__b2c__x) exp(__b2c__x)" TO g_HFILE
WRITELN "#define SGN(__b2c__x) (__b2c__x == 0 ? 0 : (__b2c__x < 0 ? -1 : 1))" TO g_HFILE
WRITELN "#define ROUND(__b2c__x) lrint(__b2c__x)" TO g_HFILE
WRITELN "#define INT(__b2c__x) lrint(__b2c__x)" TO g_HFILE
WRITELN "#define MOD(__b2c__x, __b2c__y) ((long)(__b2c__x) % (long)(__b2c__y))" TO g_HFILE
WRITELN "#define EVEN(__b2c__x) (((long)(__b2c__x) % 2 == 0) ? 1 : 0)" TO g_HFILE
WRITELN "#define ODD(__b2c__x) (((long)(__b2c__x) % 2 != 0) ? 1 : 0)" TO g_HFILE
WRITELN "#define FLOOR(__b2c__x) (long)floor(__b2c__x)" TO g_HFILE
WRITELN "#define ABS(__b2c__x) (long)abs(__b2c__x)" TO g_HFILE
WRITELN "#define RND random()" TO g_HFILE
IF INSTR(OS$, "SunOS") OR INSTR(OS$, "OSF1") THEN
WRITELN "#define MAXRANDOM 2147483647" TO g_HFILE
ELSE
WRITELN "#define MAXRANDOM RAND_MAX" TO g_HFILE
END IF
WRITELN "#define RANDOM(__b2c__x) ((__b2c__x != 0) ? random()/(MAXRANDOM/__b2c__x) : 0)" TO g_HFILE
WRITELN "#define RANDOM(__b2c__x) ((__b2c__x != 0) ? random()/(MAXRANDOM/__b2c__x) : 0)" TO g_HFILE
WRITELN "/* Other functions */" TO g_HFILE
WRITELN "#define VAL(__b2c__x) ((__b2c__x != NULL) ? atof(__b2c__x) : 0)" TO g_HFILE
WRITELN "/* Unix functions */" TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#define SYSTEM(__b2c__x) do {if (__b2c__x != NULL) {RETVAL = system(__b2c__x); if(WIFEXITED(RETVAL)) RETVAL = WEXITSTATUS(RETVAL);} else RETVAL=0;} while(0)" TO g_HFILE
WRITELN "/* String functions */" TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "char *__b2c__strndup(const char *__b2c__s, size_t __b2c__n){size_t __b2c__avail;" TO g_HFILE
WRITELN "char *__b2c__p; if (!__b2c__s) return 0; __b2c__avail = strlen(__b2c__s) + 1;" TO g_HFILE
WRITELN "if (__b2c__avail > __b2c__n + 1) __b2c__avail = __b2c__n + 1; __b2c__p = malloc(__b2c__avail);" TO g_HFILE
WRITELN "memcpy(__b2c__p, __b2c__s, __b2c__avail); __b2c__p[__b2c__avail - 1] = '\\0'; return __b2c__p;}" TO g_HFILE
WRITELN "char __b2c__input__buffer[", g_BUFFER_SIZE, "];" TO g_HFILE
WRITELN "char* __b2c__sbuffer[", g_MAX_BUFFERS, "] = { NULL };" TO g_HFILE
WRITELN "int __b2c__sbuffer_ptr = 0;" TO g_HFILE
WRITELN "char* __b2c__rbuffer[", g_MAX_RBUFFERS, "] = { NULL };" TO g_HFILE
WRITELN "int __b2c__rbuffer_ptr = 0;" TO g_HFILE
WRITELN "static jmp_buf __b2c__gosub_buffer[", g_MAX_RBUFFERS, "] = { 0 };" TO g_HFILE
WRITELN "int __b2c__gosub_buffer_ptr = -1;" TO g_HFILE
WRITELN "/* Temporary pointer to perform assignments */" TO g_HFILE
WRITELN "char *__b2c__assign = NULL;" TO g_HFILE
WRITELN "char *__b2c__split = NULL; char *__b2c__split_tmp = NULL; char *__b2c__split_ptr = NULL;" TO g_HFILE
WRITELN "char *ERR", g_STRINGSIGN$, "(int);" TO g_HFILE
WRITELN "/* Functions for sort */" TO g_HFILE
WRITELN "int __b2c__sortnrd(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(double*)__b2c__a==*(double*)__b2c__b) return 0; else if (*(double*)__b2c__a < *(double*)__b2c__b) return -1; else return 1;}" TO g_HFILE
WRITELN "int __b2c__sortnrd_down(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(double*)__b2c__a==*(double*)__b2c__b) return 0; else if (*(double*)__b2c__a < *(double*)__b2c__b) return 1; else return -1;}" TO g_HFILE
WRITELN "int __b2c__sortnrf(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(float*)__b2c__a==*(float*)__b2c__b) return 0; else if (*(float*)__b2c__a < *(float*)__b2c__b) return -1; else return 1;}" TO g_HFILE
WRITELN "int __b2c__sortnrf_down(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(float*)__b2c__a==*(float*)__b2c__b) return 0; else if (*(float*)__b2c__a < *(float*)__b2c__b) return 1; else return -1;}" TO g_HFILE
WRITELN "int __b2c__sortnrl(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(long*)__b2c__a==*(long*)__b2c__b) return 0; else if (*(long*)__b2c__a < *(long*)__b2c__b) return -1; else return 1;}" TO g_HFILE
WRITELN "int __b2c__sortnrl_down(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(long*)__b2c__a==*(long*)__b2c__b) return 0; else if (*(long*)__b2c__a < *(long*)__b2c__b) return 1; else return -1;}" TO g_HFILE
WRITELN "int __b2c__sortnri(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(int*)__b2c__a==*(int*)__b2c__b) return 0; else if (*(int*)__b2c__a < *(int*)__b2c__b) return -1; else return 1;}" TO g_HFILE
WRITELN "int __b2c__sortnri_down(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if (*(int*)__b2c__a==*(int*)__b2c__b) return 0; else if (*(int*)__b2c__a < *(int*)__b2c__b) return 1; else return -1;}" TO g_HFILE
WRITELN "int __b2c__sortstr(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if(*(char **)__b2c__a == NULL) return -1; if(*(char **)__b2c__b == NULL) return 1; return strcmp(*(char **) __b2c__a, *(char **) __b2c__b);}" TO g_HFILE
WRITELN "int __b2c__sortstr_down(const void *__b2c__a, const void *__b2c__b)" TO g_HFILE
WRITELN "{if(*(char **)__b2c__a == NULL) return -1; if(*(char **)__b2c__b == NULL) return 1; return strcmp(*(char **) __b2c__b, *(char **) __b2c__a);}" TO g_HFILE
WRITELN "/* Actual functions */" TO g_HFILE
WRITELN "char* __b2c__curdir(void){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "*sizeof(char));" TO g_HFILE
WRITELN "return (getcwd(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "));}" TO g_HFILE
WRITELN "#define CURDIR", g_STRINGSIGN$, " __b2c__curdir()" TO g_HFILE
WRITELN "char* __b2c__reverse(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__s)+2)*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)+1);" TO g_HFILE
WRITELN "for(__b2c__i=0;__b2c__i= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, "*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_MAX_DIGITS, ");" TO g_HFILE
WRITELN "if(floor(d) == d) snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%ld\", (long)d); else snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%.10g\", d);" TO g_HFILE
WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define STR", g_STRINGSIGN$, "(x) __b2c__str(x)" TO g_HFILE
WRITELN "char* __b2c__concat(char *__b2c__first, ...){char *__b2c__tmp; va_list __b2c__ap; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "if(__b2c__first != NULL) { __b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__first)+1)*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__first)+1)*sizeof(char)); strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first);}" TO g_HFILE
WRITELN "else {__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], 2*sizeof(char)); strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], \"\");} va_start(__b2c__ap, __b2c__first);" TO g_HFILE
WRITELN "while((__b2c__tmp = va_arg(__b2c__ap, char *)) != NULL) {__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__tmp)+strlen(__b2c__sbuffer[__b2c__sbuffer_ptr])+1)*sizeof(char));" TO g_HFILE
WRITELN "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__tmp);} va_end(__b2c__ap); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define CONCAT", g_STRINGSIGN$, "(...) __b2c__concat(__VA_ARGS__, (char*)NULL)" TO g_HFILE
WRITELN "char* __b2c__left(char *__b2c__src, long __b2c__n){if(__b2c__src == NULL || __b2c__n > strlen(__b2c__src) || __b2c__n < 0) return(__b2c__src);" TO g_HFILE
WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__src)+1)*sizeof(char)); strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src, (__b2c__n));" TO g_HFILE
WRITELN "return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define LEFT", g_STRINGSIGN$, "(__b2c__x, __b2c__y) __b2c__left(__b2c__x, __b2c__y)" TO g_HFILE
WRITELN "char* __b2c__right(char *__b2c__src, long __b2c__n){if(__b2c__src == NULL || __b2c__n > strlen(__b2c__src) || __b2c__n < 0) return(__b2c__src);" TO g_HFILE
WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__src)+1)*sizeof(char)); strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src+ strlen(__b2c__src)- __b2c__n);" TO g_HFILE
WRITELN "return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define RIGHT", g_STRINGSIGN$, "(__b2c__x, __b2c__y) __b2c__right(__b2c__x, __b2c__y)" TO g_HFILE
WRITELN "char* __b2c__mid(char *__b2c__src, ...){ va_list __b2c__ap; long __b2c__start, __b2c__end; if(__b2c__src == NULL || strlen(__b2c__src) == 0) return(\"\");" TO g_HFILE
WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, (strlen(__b2c__src)+1)*sizeof(char)); va_start(__b2c__ap, __b2c__src);" TO g_HFILE
WRITELN "__b2c__start = va_arg(__b2c__ap, long); if(__b2c__start < 1) return(__b2c__src); if(__b2c__start > strlen(__b2c__src)) return(\"\"); __b2c__end = va_arg(__b2c__ap, long); if((__b2c__end) < 0 || (__b2c__end) > strlen (__b2c__src)) __b2c__end = strlen(__b2c__src)-__b2c__start+1;" TO g_HFILE
WRITELN "strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__src+(long)(__b2c__start)-1, (__b2c__end)); va_end(__b2c__ap); return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define MID", g_STRINGSIGN$, "(__b2c__string, ...) __b2c__mid(__b2c__string, __VA_ARGS__, -1)" TO g_HFILE
WRITELN "long __b2c__instr(char *__b2c__first, ...){char *__b2c__tmp; char *__b2c__res; int __b2c__pos; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "va_list __b2c__ap; if(__b2c__first == NULL) return (0); __b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__first)+1)*sizeof(char));" TO g_HFILE
WRITELN "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first); va_start(__b2c__ap, __b2c__first);" TO g_HFILE
WRITELN "__b2c__tmp = va_arg(__b2c__ap, char *); if(__b2c__tmp == NULL || strlen(__b2c__tmp) == 0) return (0);__b2c__pos = va_arg(__b2c__ap, int);" TO g_HFILE
WRITELN "if(__b2c__pos <= 0) __b2c__pos = 1; va_end(__b2c__ap); __b2c__res = strstr(__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__pos - 1, __b2c__tmp);" TO g_HFILE
WRITELN "if(__b2c__res == NULL) return (0); return (__b2c__res - __b2c__sbuffer[__b2c__sbuffer_ptr] + 1);}" TO g_HFILE
WRITELN "#define INSTR(...) __b2c__instr(__VA_ARGS__, -1)" TO g_HFILE
WRITELN "long __b2c__instrrev (char *__b2c__first, ...){char *__b2c__tmp;char *__b2c__res = NULL;char *__b2c__found = NULL;int __b2c__pos; __b2c__sbuffer_ptr++;if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "va_list __b2c__ap;if (__b2c__first == NULL) return (0); __b2c__sbuffer[__b2c__sbuffer_ptr] = (char *) realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen (__b2c__first) + 1) * sizeof (char)); strcpy (__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__first);" TO g_HFILE
WRITELN "va_start (__b2c__ap, __b2c__first); __b2c__tmp = va_arg (__b2c__ap, char *); if (__b2c__tmp == NULL || strlen (__b2c__tmp) == 0) return (0); __b2c__pos = va_arg (__b2c__ap, int); if (__b2c__pos < 0) __b2c__pos = 0;" TO g_HFILE
WRITELN "va_end (__b2c__ap); if(__b2c__pos > 0) *(__b2c__sbuffer[__b2c__sbuffer_ptr]+strlen(__b2c__first)-__b2c__pos) = 0; __b2c__found = __b2c__sbuffer[__b2c__sbuffer_ptr]; do {__b2c__res = strstr (__b2c__found, __b2c__tmp);" TO g_HFILE
WRITELN "if(__b2c__res != NULL) __b2c__found = __b2c__res+1;} while (__b2c__res != NULL); if (__b2c__option_startpoint){if(strlen(__b2c__first) - (__b2c__found - __b2c__sbuffer[__b2c__sbuffer_ptr])+1 > strlen(__b2c__first)) return 0;" TO g_HFILE
WRITELN "return (long)(strlen(__b2c__first) - (__b2c__found - __b2c__sbuffer[__b2c__sbuffer_ptr])+1);} return (long)(__b2c__found - __b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define INSTRREV(...) __b2c__instrrev(__VA_ARGS__, -1)" TO g_HFILE
WRITELN "char* __b2c__spc(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 32, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define SPC", g_STRINGSIGN$, "(x) ((x > -1) ? __b2c__spc(x) : \"\")" TO g_HFILE
WRITELN "char* __b2c__tab(int __b2c__x){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 9, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define TAB", g_STRINGSIGN$, "(x) ((x > -1) ? __b2c__tab(x) : \"\")" TO g_HFILE
WRITELN "char* __b2c__fill(unsigned long __b2c__x, unsigned char __b2c__y){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, __b2c__x*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__y, __b2c__x); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define FILL", g_STRINGSIGN$, "(x, y) ((y > -1 && y < 256) ? __b2c__fill(x, y) : \"\")" TO g_HFILE
WRITELN "char* __b2c__chop(char *__b2c__src, ...){char *__b2c__tmp, *__b2c__str; int __b2c__i, __b2c__loc = 0; va_list __b2c__ap; if(strlen(__b2c__src) == 0) return(__b2c__src);" TO g_HFILE
WRITELN "va_start (__b2c__ap, __b2c__src); __b2c__str = va_arg (__b2c__ap, char*); if(__b2c__str == 0) __b2c__str = (char*)__b2c__chop_default; else __b2c__loc = va_arg (__b2c__ap, int); va_end (__b2c__ap);" TO g_HFILE
WRITELN "if(__b2c__loc == 0 || __b2c__loc == 1) {while (*__b2c__src != '\\0') {for(__b2c__i = 0; __b2c__i < strlen(__b2c__str); __b2c__i++) {if (*__b2c__src == *(__b2c__str+__b2c__i)) {__b2c__src++; break; } }" TO g_HFILE
WRITELN "if(__b2c__i == strlen(__b2c__str)) break;} if (*__b2c__src == '\\0') return(\"\");} __b2c__tmp = __b2c__src + strlen(__b2c__src) - 1;" TO g_HFILE
WRITELN "if(__b2c__loc == 0 || __b2c__loc == 2) {while (__b2c__tmp >= __b2c__src && *__b2c__tmp != '\\0') {for(__b2c__i = 0; __b2c__i < strlen(__b2c__str); __b2c__i++) {if (*__b2c__tmp == *(__b2c__str+__b2c__i))" TO g_HFILE
WRITELN "{__b2c__tmp--; break; } } if(__b2c__i == strlen(__b2c__str)) break;} } __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__src)+1)*sizeof(char));" TO g_HFILE
WRITELN "for(__b2c__i = 0; __b2c__i <= __b2c__tmp - __b2c__src; __b2c__i++) __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=__b2c__src[__b2c__i];" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i] = '\\0'; return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define CHOP", g_STRINGSIGN$, "(...) __b2c__chop(__VA_ARGS__, 0)" TO g_HFILE
WRITELN "char* __b2c__replace(char* __b2c__x, char* __b2c__y, char* __b2c__z){" TO g_HFILE
WRITELN "char *__b2c__tmp, *__b2c__buf, *__b2c__haystack, *__b2c__dup = NULL; __b2c__sbuffer_ptr++;" TO g_HFILE
WRITELN "if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0; __b2c__haystack = strdup(__b2c__x); __b2c__dup = __b2c__haystack;" TO g_HFILE
WRITELN "__b2c__buf = calloc(1, sizeof(char)); while((__b2c__tmp = strstr(__b2c__haystack, __b2c__y)) != NULL) {*__b2c__tmp = '\\0';" TO g_HFILE
WRITELN "__b2c__buf = realloc(__b2c__buf, (strlen(__b2c__buf) + strlen(__b2c__haystack) + strlen(__b2c__z) + 1)*sizeof(char));" TO g_HFILE
WRITELN "strcat(__b2c__buf, __b2c__haystack);strcat(__b2c__buf, __b2c__z);__b2c__haystack = __b2c__tmp+strlen(__b2c__y);}" TO g_HFILE
WRITELN "__b2c__buf = realloc(__b2c__buf, (strlen(__b2c__buf) + strlen(__b2c__haystack) + 1)*sizeof(char));strcat(__b2c__buf, __b2c__haystack);" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], (strlen(__b2c__buf)+1)*sizeof(char));" TO g_HFILE
WRITELN "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf);free(__b2c__buf);free(__b2c__dup);return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define REPLACE", g_STRINGSIGN$, "(x, y, z)((x!=NULL && y!=NULL && z!= NULL) ? __b2c__replace(x, y, z) : 0)" TO g_HFILE
WRITELN "#define LEN(x) ((x != NULL) ? strlen(x) : 0)" TO g_HFILE
WRITELN "#define EQUAL(__b2c__x, __b2c__y) ((__b2c__x != NULL && __b2c__y != NULL && __b2c__option_compare == 0) ? !strcmp(__b2c__x, __b2c__y) : ((__b2c__x != NULL && __b2c__y != NULL && __b2c__option_compare == 1) ? !strcasecmp(__b2c__x, __b2c__y) : 0) )" TO g_HFILE
WRITELN "char* __b2c__getenv(char *__b2c__env){static char* __b2c__tmp; __b2c__tmp = getenv(__b2c__env); if (__b2c__tmp == NULL)" TO g_HFILE
WRITELN "{return \"\";} return __b2c__tmp;}" TO g_HFILE
WRITELN "#define GETENVIRON", g_STRINGSIGN$, "(x) ((x != NULL) ? __b2c__getenv(x) : \"null\")" TO g_HFILE
WRITELN "#define SETENVIRON(x, y) if(x != NULL && y != NULL) setenv(x, y, 1)" TO g_HFILE
WRITELN "/* CHAR functions */" TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "char* __b2c__ucase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=toupper(__b2c__s[__b2c__i]);}" TO g_HFILE
WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define UCASE", g_STRINGSIGN$, "(x) ((x != NULL) ? __b2c__ucase(x) : \"null\")" TO g_HFILE
WRITELN "char* __b2c__lcase(char *__b2c__s){int __b2c__i; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, strlen(__b2c__s)*sizeof(char)+1*sizeof(char));" TO g_HFILE
WRITELN "for(__b2c__i=0; __b2c__i < strlen(__b2c__s); __b2c__i++){__b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__i]=tolower(__b2c__s[__b2c__i]);}" TO g_HFILE
WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define LCASE", g_STRINGSIGN$, "(x) ((x != NULL) ? __b2c__lcase(x) : \"null\")" TO g_HFILE
WRITELN "/* I/O functions */" TO g_HFILE
WRITELN "FILE *__b2c__inFile; FILE *__b2c__outFile; int __b2c__Byte; struct dirent *__b2c__dir;" TO g_HFILE
WRITELN "char* __b2c__dec2hex(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ");" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_MAX_DIGITS, ");" TO g_HFILE
WRITELN "snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%X\", __b2c__i); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "long __b2c__hex2dec(char *__b2c__h){unsigned int __b2c__i; if(sscanf(__b2c__h, \"%X\", &__b2c__i) == EOF && !__b2c__trap){ERROR = 5;" TO g_HFILE
WRITELN "fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} return(long)(__b2c__i);}" TO g_HFILE
WRITELN "unsigned char __b2c__char2asc(char *__b2c__c){return (unsigned char)*__b2c__c;}" TO g_HFILE
WRITELN "char* __b2c__asc2char(int __b2c__i){__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], 2*sizeof(char));" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, 2*sizeof(char)); snprintf(__b2c__sbuffer[__b2c__sbuffer_ptr], 2, \"%c\", __b2c__i);" TO g_HFILE
WRITELN "return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "/* Function FILEEXISTS contributed by Armando Rivera */ " TO g_HFILE
WRITELN "long __b2c__fileexists(const char *__b2c__x) {struct stat __b2c__buf; if (stat(__b2c__x, &__b2c__buf) != -1) return 1; return 0;}" TO g_HFILE
WRITELN "#define FILEEXISTS(x) __b2c__fileexists(x)" TO g_HFILE
WRITELN "long __b2c__filelen(const char *__b2c__x) {struct stat __b2c__buf; if(stat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap){ERROR = 24; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE
WRITELN "if(__b2c__x == NULL || stat(__b2c__x, &__b2c__buf) < 0) return -1; else return(long)(__b2c__buf.st_size);}" TO g_HFILE
WRITELN "#define FILELEN(x) __b2c__filelen(x)" TO g_HFILE
WRITELN "long __b2c__filetime(const char *__b2c__x, int __b2c__y) {struct stat __b2c__buf; if(stat(__b2c__x, &__b2c__buf) < 0 && !__b2c__trap){ERROR = 24; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE
WRITELN "if(__b2c__x == NULL || stat(__b2c__x, &__b2c__buf) < 0 || __b2c__y < 0 || __b2c__y > 2) return -1; switch(__b2c__y) {case 0: return(long)(__b2c__buf.st_atime); break;" TO g_HFILE
WRITELN "case 1: return(long)(__b2c__buf.st_mtime); break; case 2: return(long)(__b2c__buf.st_ctime); break;} }" TO g_HFILE
WRITELN "#define FILETIME(x, y) __b2c__filetime(x, y)" TO g_HFILE
WRITELN "long __b2c__filetype(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_HFILE
WRITELN "{ERROR = 24; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE
WRITELN "if (S_ISREG(__b2c__buf.st_mode)) __b2c_fs = 1; if (S_ISDIR(__b2c__buf.st_mode)) __b2c_fs = 2;" TO g_HFILE
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_HFILE
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_HFILE
WRITELN "#define FILETYPE(x) __b2c__filetype(x)" TO g_HFILE
WRITELN "long __b2c__search(FILE* __b2c__x, char* __b2c__y){long __b2c__off, __b2c__pos; char* __b2c__ptr; size_t __b2c__tot;" TO g_HFILE
WRITELN "if(__b2c__x == NULL && !__b2c__trap){ERROR = 2; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE
WRITELN "if(__b2c__y == NULL && !__b2c__trap){ERROR = 25; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE
WRITELN "__b2c__pos = ftell(__b2c__x); __b2c__ptr = (char*)malloc((strlen(__b2c__y)+1)*sizeof(char)); __b2c__off = 0; do {" TO g_HFILE
WRITELN "fseek(__b2c__x, __b2c__off, SEEK_SET);memset(__b2c__ptr, 0, sizeof(char)*(strlen(__b2c__y)+1));" TO g_HFILE
WRITELN "__b2c__tot = fread(__b2c__ptr, sizeof(char), strlen(__b2c__y), __b2c__x);__b2c__off+=1;" TO g_HFILE
WRITELN "} while(!feof(__b2c__x) && strncmp(__b2c__ptr, __b2c__y, strlen(__b2c__y)));" TO g_HFILE
WRITELN "if(strncmp(__b2c__ptr, __b2c__y, strlen(__b2c__y))) __b2c__off = 0; fseek(__b2c__x, __b2c__pos, SEEK_SET); free(__b2c__ptr); return (--__b2c__off);}" TO g_HFILE
WRITELN "#define SEARCH(x, y) __b2c__search(x, y)" TO g_HFILE
WRITELN "char *__b2c__exec(char *__b2c__x, ...){int __b2c__r, __b2c__len, __b2c__i, __b2c__page; int __b2c__wpipe[2], __b2c__rpipe[2]; char *__b2c__str, *__b2c__ans = NULL; va_list __b2c__ap;" TO g_HFILE
WRITELN "va_start(__b2c__ap, __b2c__x); __b2c__str = va_arg (__b2c__ap, char*); va_end(__b2c__ap); if (pipe (__b2c__rpipe) < 0 || pipe (__b2c__wpipe) < 0){if(!__b2c__trap) {ERROR=29;fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}}" TO g_HFILE
WRITELN "if ((__b2c__r = fork ()) < 0){if(!__b2c__trap) {ERROR=29;fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}} else if (__b2c__r == 0){" TO g_HFILE
WRITELN "close(__b2c__wpipe[1]);close (__b2c__rpipe[0]);dup2 (__b2c__wpipe[0], 0);close (__b2c__wpipe[0]);dup2 (__b2c__rpipe[1], 1);close (__b2c__rpipe[1]); __b2c__r = system (__b2c__x); if(WIFEXITED(__b2c__r)) RETVAL = WEXITSTATUS(__b2c__r); else RETVAL=0; exit(RETVAL);}" TO g_HFILE
WRITELN "else{close (__b2c__wpipe[0]);close (__b2c__rpipe[1]); __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "*sizeof(char) + 1);__b2c__ans = (char*)malloc(", g_BUFFER_SIZE, " *sizeof(char)); __b2c__len = 0;__b2c__page = 0;" TO g_HFILE
WRITELN "if(__b2c__str!=NULL) __b2c__i = write(__b2c__wpipe[1], __b2c__str, strlen(__b2c__str)+1); wait(&RETVAL); RETVAL = WEXITSTATUS(RETVAL); do{__b2c__i = read (__b2c__rpipe[0], __b2c__ans, ", g_BUFFER_SIZE, ");if (__b2c__i == -1 && !__b2c__trap){ERROR=30;fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE
WRITELN "if (__b2c__i == 0)break;if (__b2c__len + __b2c__i > ", g_BUFFER_SIZE, " *__b2c__page + 1){__b2c__page++;__b2c__sbuffer[__b2c__sbuffer_ptr] = realloc (__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "*__b2c__page + 1);" TO g_HFILE
WRITELN "if (__b2c__sbuffer[__b2c__sbuffer_ptr] == NULL && !__b2c__trap){ERROR=6; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } memcpy (__b2c__sbuffer[__b2c__sbuffer_ptr] + __b2c__len, __b2c__ans, __b2c__i);" TO g_HFILE
WRITELN " __b2c__len += __b2c__i;} while (__b2c__i > 0); __b2c__sbuffer[__b2c__sbuffer_ptr][__b2c__len] = '\\0';close (__b2c__wpipe[1]);" TO g_HFILE
WRITELN "close (__b2c__rpipe[0]);free (__b2c__ans);} return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define EXEC", g_STRINGSIGN$, "(...) __b2c__exec(__VA_ARGS__, (char*)NULL)" TO g_HFILE
WRITELN "#define ENDFILE(x) feof(x)" TO g_HFILE
WRITELN "#define TELL(x) ftell(x)" TO g_HFILE
WRITELN "#define HEX", g_STRINGSIGN$, "(x) __b2c__dec2hex(x)" TO g_HFILE
WRITELN "#define DEC(x) __b2c__hex2dec(x)" TO g_HFILE
WRITELN "#define ASC(x) __b2c__char2asc(x)" TO g_HFILE
WRITELN "#define CHR", g_STRINGSIGN$, "(__b2c__x) __b2c__asc2char(__b2c__x)" TO g_HFILE
WRITELN "#define MEMTELL(x) (long)x" TO g_HFILE
WRITELN "/* Dynamic loading, errors */" TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "/* GETKEY */" TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "long __b2c__getch(){long __b2c__ch; struct termios __b2c__oldt, __b2c__newt; tcgetattr(STDIN_FILENO, &__b2c__oldt);" TO g_HFILE
WRITELN "__b2c__newt = __b2c__oldt; __b2c__newt.c_lflag &= ~(ICANON | ECHO); __b2c__newt.c_cc[VMIN]=1; __b2c__newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__newt);" TO g_HFILE
WRITELN "__b2c__ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__oldt); return __b2c__ch;} " TO g_HFILE
WRITELN "#define GETKEY __b2c__getch()" TO g_HFILE
WRITELN "long __b2c__getxy(int __b2c__type){char __b2c__asw[", g_BUFFER_SIZE, "]; struct termios __b2c__old, __b2c__new; int __b2c__len, __b2c__x, __b2c__y; ssize_t __b2c__tot;" TO g_HFILE
WRITELN "tcgetattr(STDIN_FILENO, &__b2c__old); __b2c__new = __b2c__old;__b2c__new.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__new);" TO g_HFILE
WRITELN "__b2c__tot = write(STDOUT_FILENO, \"\\033[6n\", strlen(\"\\033[6n\")); __b2c__len = read(STDIN_FILENO, __b2c__asw, ", g_BUFFER_SIZE, ");__b2c__asw[__b2c__len] = '\\0'; " TO g_HFILE
WRITELN "tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__old); sscanf(__b2c__asw, \"\\033[%d;%dR\", &__b2c__y, &__b2c__x); if (!__b2c__type) return(long)__b2c__x; return(long)__b2c__y;}" TO g_HFILE
WRITELN "#define GETX __b2c__getxy(0)" TO g_HFILE
WRITELN "#define GETY __b2c__getxy(1)" TO g_HFILE
WRITELN "long __b2c__screen(int __b2c__type){long __b2c__x; fprintf(stdout,\"\\033[s\"); fprintf(stdout,\"\\033[?25l\"); fprintf(stdout,\"\\033[999;999H\"); fflush(stdout);" TO g_HFILE
WRITELN "__b2c__x = __b2c__getxy(__b2c__type); fprintf(stdout,\"\\033[u\"); fprintf(stdout,\"\\033[?25h\"); fflush(stdout); return(__b2c__x); }" TO g_HFILE
WRITELN "#define COLUMNS __b2c__screen(0)" TO g_HFILE
WRITELN "#define ROWS __b2c__screen(1)" TO g_HFILE
WRITELN "/* Constants, logical stuff */" TO g_HFILE
WRITELN "#define PI 3.14159265" TO g_HFILE
WRITELN "#define NOT(__b2c__x) (!(__b2c__x))" TO g_HFILE
WRITELN "#define AND &&" TO g_HFILE
WRITELN "#define OR ||" TO g_HFILE
WRITELN "#define EQ ==" TO g_HFILE
WRITELN "#define IS ==" TO g_HFILE
WRITELN "#define NE !=" TO g_HFILE
WRITELN "#define ISNOT !=" TO g_HFILE
WRITELN "#define TRUE 1" TO g_HFILE
WRITELN "#define FALSE 0" TO g_HFILE
WRITELN "#define NL", g_STRINGSIGN$, " \"\\n\"" TO g_HFILE
WRITELN "#define STRING char*" TO g_HFILE
WRITELN "#define NUMBER long" TO g_HFILE
WRITELN "#define FLOATING double" TO g_HFILE
WRITELN "#define ISTRUE(__b2c__x) (__b2c__x!=0)" TO g_HFILE
WRITELN "#define ISFALSE(__b2c__x) (__b2c__x==0)" TO g_HFILE
WRITELN "#define SIZEOF(__b2c__x) sizeof(__b2c__x)" TO g_HFILE
WRITELN "/* Date and time */" TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "#define NOW (long)time(NULL)" TO g_HFILE
WRITELN "long __b2c__time(time_t __b2c__now, int __b2c__which){struct tm *ts; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr],", g_MAX_DIGITS, ");" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_MAX_DIGITS, "); ts = localtime(&__b2c__now); switch(__b2c__which) { case 1: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%d\", ts); break;" TO g_HFILE
WRITELN "case 2: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%m\", ts); break; case 3: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%Y\", ts); break;" TO g_HFILE
WRITELN "case 4: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%H\", ts); break; case 5: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%M\", ts); break;" TO g_HFILE
WRITELN "case 6: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%S\", ts); break; case 7: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%W\", ts); break;}" TO g_HFILE
WRITELN "return(atol(__b2c__sbuffer[__b2c__sbuffer_ptr]));}" TO g_HFILE
WRITELN "#define DAY(x) __b2c__time(x, 1)" TO g_HFILE
WRITELN "#define MONTH(x) __b2c__time(x, 2)" TO g_HFILE
WRITELN "#define YEAR(x) __b2c__time(x, 3)" TO g_HFILE
WRITELN "#define HOUR(x) __b2c__time(x, 4)" TO g_HFILE
WRITELN "#define MINUTE(x) __b2c__time(x, 5)" TO g_HFILE
WRITELN "#define SECOND(x) __b2c__time(x, 6)" TO g_HFILE
WRITELN "#define WEEK(x) __b2c__time(x, 7)" TO g_HFILE
WRITELN "char* __b2c__datename(time_t __b2c__now, int __b2c__which){struct tm *ts; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ");" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_MAX_DIGITS, "); ts = localtime(&__b2c__now); switch(__b2c__which){case 1: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%A\", ts); break;" TO g_HFILE
WRITELN "case 2: strftime(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_MAX_DIGITS, ", \"%B\", ts); break;} return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define WEEKDAY", g_STRINGSIGN$, "(x) __b2c__datename(x, 1)" TO g_HFILE
WRITELN "#define MONTH", g_STRINGSIGN$, "(x) __b2c__datename(x, 2)" TO g_HFILE
WRITELN "unsigned long __b2c__epoch(int __b2c__year, int __b2c__month, int __b2c__day, int __b2c__hour, int __b2c__minute, int __b2c__second){" TO g_HFILE
WRITELN "struct tm tm; time_t __b2c__t; tm.tm_year = __b2c__year - 1900; tm.tm_mon = __b2c__month - 1; tm.tm_mday = __b2c__day;" TO g_HFILE
WRITELN "tm.tm_hour = __b2c__hour; tm.tm_min = __b2c__minute; tm.tm_sec = __b2c__second;" TO g_HFILE
WRITELN "tm.tm_isdst = -1; __b2c__t = mktime(&tm); if (__b2c__t == -1) return (0); return(long) __b2c__t; }" TO g_HFILE
WRITELN "#define TIMEVALUE(x,y,z,a,b,c) __b2c__epoch(x,y,z,a,b,c)" TO g_HFILE
WRITELN "char* __b2c__os(void){struct utsname __b2c__buf; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, ");" TO g_HFILE
WRITELN "memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_BUFFER_SIZE, "); if(uname(&__b2c__buf) < 0 && !__b2c__trap) {ERROR = 26; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE
WRITELN "strcpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.sysname); strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], \" \");" TO g_HFILE
WRITELN "strcat(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__buf.machine); return(__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define OS", g_STRINGSIGN$, " __b2c__os()" TO g_HFILE
WRITELN "/* Peek and Poke */" TO g_HFILE
WRITELN "struct stat __b2c__sb;" TO g_HFILE
WRITELN "int __b2c__memory__check(void* __b2c__x) {if (stat(__b2c__x, &__b2c__sb) == -1 && errno == EFAULT) return(1); else return(0); }" TO g_HFILE
WRITELN "long __b2c__malloc(long __b2c__x) {void *__b2c__mem; if(__b2c__x==0) return(0); switch(__b2c__memtype) {case 1: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(char)); break;" TO g_HFILE
WRITELN "case 2: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(short)); break; case 3: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(int)); break;" TO g_HFILE
WRITELN "case 4: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(long)); break; case 5: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(float)); break;" TO g_HFILE
WRITELN "case 6: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(double)); break; case 7: __b2c__mem = calloc(__b2c__x+__b2c__option_memstream, sizeof(char)); break;}" TO g_HFILE
WRITELN "if(__b2c__mem == NULL && !__b2c__trap) {ERROR = 6; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} return(long)__b2c__mem;}" TO g_HFILE
WRITELN "#define MEMORY(__b2c__x) __b2c__malloc(__b2c__x)" TO g_HFILE
WRITELN "void *__b2c__realloc(void* __b2c__x, long __b2c__y) {if(__b2c__x == NULL) return (NULL); if(!__b2c__trap) {if(__b2c__memory__check((char*)__b2c__x))" TO g_HFILE
WRITELN "{ERROR=1; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } switch(__b2c__memtype) {case 1: __b2c__x = realloc((void*)__b2c__x, sizeof(char)*(__b2c__y+1)); break;" TO g_HFILE
WRITELN "case 2: __b2c__x = realloc((void*)__b2c__x, sizeof(short)*(__b2c__y+1)); break; case 3: __b2c__x = realloc((void*)__b2c__x, sizeof(int)*(__b2c__y+1)); break;" TO g_HFILE
WRITELN "case 4: __b2c__x = realloc((void*)__b2c__x, sizeof(long)*(__b2c__y+1)); break; case 5: __b2c__x = realloc((void*)__b2c__x, sizeof(float)*(__b2c__y+1)); break;" TO g_HFILE
WRITELN "case 6: __b2c__x = realloc((void*)__b2c__x, sizeof(double)*(__b2c__y+1)); break; case 7: __b2c__x = realloc((void*)__b2c__x, sizeof(char)*(__b2c__y+1)); break;}" TO g_HFILE
WRITELN "if(__b2c__x == NULL && !__b2c__trap) {ERROR = 6; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} return (__b2c__x);}" TO g_HFILE
WRITELN "#define RESIZE(__b2c__x, __b2c__y) __b2c__realloc((void*)__b2c__x, __b2c__y)" TO g_HFILE
WRITELN "char __b2c__peek(char* __b2c__x) {if(!__b2c__trap) {if(__b2c__memory__check((char*) __b2c__x)) {ERROR=1; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((char)*__b2c__x);}" TO g_HFILE
WRITELN "short __b2c__peeks(short* __b2c__x) {if(!__b2c__trap) {if(__b2c__memory__check((short*) __b2c__x)) {ERROR=1; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((short)*__b2c__x);}" TO g_HFILE
WRITELN "int __b2c__peeki(int* __b2c__x) {if(!__b2c__trap) {if(__b2c__memory__check((int*) __b2c__x)) {ERROR=1; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((int)*__b2c__x);}" TO g_HFILE
WRITELN "long __b2c__peekl(long* __b2c__x) {if(!__b2c__trap) {if(__b2c__memory__check((long*) __b2c__x)) {ERROR=1; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((long)*__b2c__x);}" TO g_HFILE
WRITELN "float __b2c__peekf(float* __b2c__x) {if(!__b2c__trap) {if(__b2c__memory__check((float*) __b2c__x)) {ERROR=1; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((float)*__b2c__x);}" TO g_HFILE
WRITELN "double __b2c__peekd(double* __b2c__x) {if(!__b2c__trap) {if(__b2c__memory__check((double*) __b2c__x)) {ERROR=1; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((double)*__b2c__x);}" TO g_HFILE
WRITELN "char __b2c__peekv(char* __b2c__x) {if(!__b2c__trap) {if(__b2c__memory__check((char*) __b2c__x)) {ERROR=1; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);} } return((char)*__b2c__x);}" TO g_HFILE
WRITELN "#define PEEK(__b2c__x) (__b2c__memtype==1 ? (unsigned char)__b2c__peek((char*)__b2c__x) : (__b2c__memtype==2 ? (unsigned short)__b2c__peeks((short*)__b2c__x) : (__b2c__memtype==3 ? (unsigned int)__b2c__peeki((int*)__b2c__x) : \\" TO g_HFILE
WRITELN "(__b2c__memtype==4 ? (unsigned long)__b2c__peekl((long*)__b2c__x) : ( __b2c__memtype==5 ? (float)__b2c__peekf((float*)__b2c__x) : (__b2c__memtype==6 ? (double)__b2c__peekd((double*)__b2c__x) : (unsigned char)__b2c__peekv((char*)__b2c__x) ))))))" TO g_HFILE
WRITELN "#define ADDRESS(__b2c__x) (long)(&__b2c__x)" TO g_HFILE
WRITELN "#define FP(__b2c__x) (void*)(&__b2c__x)" TO g_HFILE
WRITELN "/* Network variables and functions */" TO g_HFILE
WRITELN "struct timeval __b2c__to; struct hostent *__b2c__he; char *__b2c__host; char *__b2c__port; int __b2c__yes = 1; char __b2c__ttl = 1; struct sockaddr_in __b2c__addr; struct ip_mreq __b2c__imreq;" TO g_HFILE
WRITELN "int __b2c__result; char __b2c__data_client[", g_BUFFER_SIZE, "] = { 0 }; char __b2c__data_server[", g_BUFFER_SIZE, "] = { 0 }; int __b2c__handle;" TO g_HFILE
WRITELN "long __b2c__netpeek(int __b2c__fd, int __b2c__usec){fd_set __b2c__rfds; struct timeval __b2c__tv; long __b2c__retval; struct termios __b2c__oldt, __b2c__newt;" TO g_HFILE
WRITELN "if(__b2c__fd == STDIN_FILENO){tcgetattr(STDIN_FILENO, &__b2c__oldt); __b2c__newt = __b2c__oldt; __b2c__newt.c_lflag &= ~(ICANON | ECHO); __b2c__newt.c_cc[VMIN]=1; __b2c__newt.c_cc[VTIME]=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__newt);}" TO g_HFILE
WRITELN "FD_ZERO(&__b2c__rfds); FD_SET(__b2c__fd, &__b2c__rfds);__b2c__tv.tv_usec = (__b2c__usec%1000)*1000; __b2c__tv.tv_sec = __b2c__usec/1000;" TO g_HFILE
WRITELN "__b2c__retval = select(__b2c__fd + 1, &__b2c__rfds, NULL, NULL, &__b2c__tv); if (__b2c__retval == -1 && !__b2c__trap) {ERROR = 16; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR);}" TO g_HFILE
WRITELN "if(__b2c__fd == STDIN_FILENO){if(__b2c__retval) if(read(__b2c__fd, &__b2c__retval, 1)==0) __b2c__retval=0; tcsetattr(STDIN_FILENO, TCSANOW, &__b2c__oldt);} return(__b2c__retval);}" TO g_HFILE
WRITELN "#define WAIT(x, y) __b2c__netpeek(x, y)" TO g_HFILE
WRITELN "char* __b2c__nethost(char* __b2c__host) {int __b2c__y; int __b2c__flag = 0; struct in_addr __b2c__address; __b2c__sbuffer_ptr++; if(__b2c__sbuffer_ptr >= ", g_MAX_BUFFERS, ") __b2c__sbuffer_ptr=0;" TO g_HFILE
WRITELN "__b2c__sbuffer[__b2c__sbuffer_ptr] = (char*)realloc(__b2c__sbuffer[__b2c__sbuffer_ptr], ", g_BUFFER_SIZE, "); memset(__b2c__sbuffer[__b2c__sbuffer_ptr], 0, ", g_BUFFER_SIZE, ");" TO g_HFILE
WRITELN "for(__b2c__y=0; __b2c__y < strlen(__b2c__host); __b2c__y++) {if(isalpha(*(__b2c__host+__b2c__y))) {__b2c__flag = 1; break;}} if(__b2c__flag) __b2c__he = gethostbyname(__b2c__host); " TO g_HFILE
WRITELN "else {if(inet_aton(__b2c__host, &__b2c__address)) __b2c__he = gethostbyaddr((void*)&__b2c__address, sizeof(struct in_addr), AF_INET); } if (__b2c__he == NULL || __b2c__he->h_addr == NULL || __b2c__he->h_name == NULL)" TO g_HFILE
WRITELN "{if(!__b2c__trap){ERROR = 11; fprintf(stderr, \"%s\\n\", ERR", g_STRINGSIGN$, "(ERROR)); exit(ERROR); } else strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], \"Host not found\", ", g_BUFFER_SIZE ,"-1); } else {if(__b2c__flag) {__b2c__addr.sin_addr = *((struct in_addr *)__b2c__he->h_addr);" TO g_HFILE
WRITELN "strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], inet_ntoa(__b2c__addr.sin_addr), ", g_BUFFER_SIZE, "-1);} else strncpy(__b2c__sbuffer[__b2c__sbuffer_ptr], __b2c__he->h_name, ", g_BUFFER_SIZE, "-1);} return (__b2c__sbuffer[__b2c__sbuffer_ptr]);}" TO g_HFILE
WRITELN "#define HOST", g_STRINGSIGN$, "(__b2c__x) __b2c__nethost(__b2c__x)" TO g_HFILE
WRITELN "/* Regex */" TO g_HFILE
WRITELN "#include " TO g_HFILE
WRITELN "long __b2c__regex(char* __b2c__x, char* __b2c__y){regex_t __b2c__reg; int __b2c__reti; char __b2c__buf[100]; __b2c__reti = regcomp(&__b2c__reg, __b2c__y, REG_EXTENDED|REG_NOSUB);" TO g_HFILE
WRITELN "if(!__b2c__trap && __b2c__reti){ERROR=27; fprintf(stderr, \"%s: \", ERR", g_STRINGSIGN$, "(ERROR)); regerror(__b2c__reti, &__b2c__reg, __b2c__buf, sizeof(__b2c__buf)); fprintf(stderr, \"%s\\n\", __b2c__buf);" TO g_HFILE
WRITELN "exit(ERROR);} __b2c__reti = regexec(&__b2c__reg, __b2c__x, 0, NULL, 0);" TO g_HFILE
WRITELN "regfree(&__b2c__reg); if( !__b2c__reti ) return (1); else return (0);}" TO g_HFILE
WRITELN "#define REGEX(x, y) __b2c__regex(x, y)" TO g_HFILE
WRITELN "/* Declare reserved variable 'ARGUMENT' */" TO g_HFILE
WRITELN "int __b2c__counter;" TO g_HFILE
WRITELN "int __b2c__arglen = 0;" TO g_HFILE
WRITELN "char *ARGUMENT", g_STRINGSIGN$, ";" TO g_HFILE
WRITELN "/* Initialize stack arrays and pointer */" TO g_HFILE
WRITELN "char **__b2c__stringstack = NULL; double *__b2c__doublestack = NULL;" TO g_HFILE
WRITELN "long *__b2c__longstack = NULL; int *__b2c__typestack = NULL;" TO g_HFILE
WRITELN "int __b2c__stackptr = 0;" TO g_HFILE
' Signal function
WRITELN "/* Signal trapping activated with TRAP */" TO g_HFILE
WRITELN "void __b2c__catch_signal(int sig){" TO g_HFILE
WRITELN "switch (sig) {case SIGABRT: fprintf(stderr, \"ERROR: signal ABORT received - internal error. Try to compile the program with TRAP LOCAL to find the cause.\\n\"); break;" TO g_HFILE
WRITELN "case SIGFPE: fprintf(stderr, \"ERROR: signal for FPE received - division by zero? Examine the calculations in the program.\\n\"); break;" TO g_HFILE
WRITELN "case SIGSEGV: fprintf(stderr, \"ERROR: signal for SEGMENTATION FAULT received - memory invalid or array out of bounds? Try to compile the program with TRAP LOCAL to find the cause.\\n\"); break;" TO g_HFILE
WRITELN "case SIGILL: fprintf(stderr, \"ERROR: signal for ILLEGAL INSTRUCTION received - executing the program on other hardware? Try to recompile the program from scratch.\\n\"); break;} exit(sig);}" TO g_HFILE
' Makedir function
WRITELN "int __b2c__makedir(char* __b2c__in){char *__b2c__i, *__b2c__dir; if(__b2c__in == NULL || strlen(__b2c__in)==0) return 0; if(*__b2c__in != '/'){__b2c__dir = (char*)malloc((strlen(__b2c__in)+2)*sizeof(char));" TO g_HFILE
WRITELN "strncpy(__b2c__dir, \"./\", 2); __b2c__dir = strcat(__b2c__dir, __b2c__in);} else __b2c__dir = strdup(__b2c__in); __b2c__i = __b2c__dir; do { __b2c__i++; while(*__b2c__i != '/' && *__b2c__i != '\\0') __b2c__i++;" TO g_HFILE
WRITELN "if(*__b2c__i == '/') {*__b2c__i = '\\0'; mkdir(__b2c__dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); *__b2c__i = '/';} else if (*__b2c__i == '\\0') mkdir(__b2c__dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);" TO g_HFILE
WRITELN "if(errno != EEXIST && errno != 0) {free(__b2c__dir); return errno;} } while (*__b2c__i != '\\0'); free(__b2c__dir); return 0;}" TO g_HFILE
' Add error function
WRITELN "/* Initialize error function */" TO g_HFILE
WRITELN "char *ERR", g_STRINGSIGN$, "(int __b2c__nr){static char __b2c__warn[", g_BUFFER_SIZE, "] = { 0 }; const char* __b2c__err;" TO g_HFILE
WRITELN "switch(__b2c__nr){" TO g_HFILE
WRITELN "case 0: strcpy(__b2c__warn,\"Success\"); break;" TO g_HFILE
WRITELN "case 1: strcpy(__b2c__warn,\"Trying to access illegal memory: \"); strncat(__b2c__warn,strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 2: strcpy(__b2c__warn,\"Error opening file: \"); strncat(__b2c__warn,strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 3: strcpy(__b2c__warn, \"Could not open library \"); __b2c__err = dlerror(); if(__b2c__err!=NULL) strncat(__b2c__warn, __b2c__err, ", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 4: strcpy(__b2c__warn, \"Symbol not found in library \"); __b2c__err = dlerror(); if(__b2c__err!=NULL) strncat(__b2c__warn, __b2c__err, ", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 5: strcpy(__b2c__warn, \"Wrong hexvalue: \"); strncat(__b2c__warn, strerror(errno), ", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 6: strcpy(__b2c__warn, \"Unable to claim memory.\"); break;" TO g_HFILE
WRITELN "case 7: strcpy(__b2c__warn, \"Unable to delete file: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 8: strcpy(__b2c__warn, \"Could not open directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 9: strcpy(__b2c__warn, \"Unable to rename file: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 10: strcpy(__b2c__warn, \"NETWORK argument should contain colon with port number\"); break;" TO g_HFILE
WRITELN "case 11: strcpy(__b2c__warn, \"Could not resolve hostname!\"); break;" TO g_HFILE
WRITELN "case 12: strcpy(__b2c__warn, \"Socket error: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 13: strcpy(__b2c__warn, \"Unable to open address: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 14: strcpy(__b2c__warn, \"Error reading from socket: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 15: strcpy(__b2c__warn, \"Error sending to socket: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 16: strcpy(__b2c__warn, \"Error checking socket: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 17: strcpy(__b2c__warn, \"Unable to bind the specified socket address: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 18: strcpy(__b2c__warn, \"Unable to listen to socket address: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 19: strcpy(__b2c__warn, \"Cannot accept incoming connection: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 20: strcpy(__b2c__warn, \"Unable to remove directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 21: strcpy(__b2c__warn, \"Unable to create directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 22: strcpy(__b2c__warn, \"Unable to change to directory: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 23: strcpy(__b2c__warn, \"GETENVIRON argument does not exist as environment variable\"); break;" TO g_HFILE
WRITELN "case 24: strcpy(__b2c__warn, \"Unable to stat file: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 25: strcpy(__b2c__warn, \"Search contains illegal string\"); break;" TO g_HFILE
WRITELN "case 26: strcpy(__b2c__warn, \"Cannot return OS name: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 27: strcpy(__b2c__warn, \"Illegal regex expression\"); break;" TO g_HFILE
WRITELN "case 28: strcpy(__b2c__warn, \"Unable to create bidirectional pipes: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 29: strcpy(__b2c__warn, \"Unable to fork process: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 30: strcpy(__b2c__warn, \"Cannot read from pipe: \"); strncat(__b2c__warn, strerror(errno),", g_BUFFER_SIZE-48, "); break;" TO g_HFILE
WRITELN "case 31: strcpy(__b2c__warn, \"Gosub nesting too deep!\"); break;" TO g_HFILE
WRITELN "}; ERROR = 0; return(__b2c__warn);}" TO g_HFILE
WRITELN "/* User program definitions */" TO g_HFILE
' Set fileposition for search in header file
g_HEADER_SEARCHPOS = FILELEN(g_HFILE$)
' Initialize the arrayfiles for DATA statement
OPEN STRINGARRAYFILE$ FOR WRITING AS STRINGARRAYFILE
WRITELN "char* __b2c__stringarray[] = {" TO STRINGARRAYFILE
OPEN FLOATARRAYFILE$ FOR WRITING AS FLOATARRAYFILE
WRITELN "double __b2c__floatarray[] = {" TO FLOATARRAYFILE
' There are no imported symbols yet
LET g_IMPORTED$ = ""
' Check if the C Preprocessor needs to run
IF ISTRUE(g_CPP) AND dialog > 0 THEN
IF ISTRUE(LEN(EXEC$("which cpp 2>/dev/null"))) THEN
SYSTEM CONCAT$("cpp -P -w ", g_SOURCEFILE$, " ", g_SOURCEFILE$, ".cpp")
FEED$ = CONCAT$(g_SOURCEFILE$, ".cpp")
g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_SOURCEFILE$, ".cpp")
ELSE
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "ERROR: the C Preprocessor 'cpp' not found on this system!", -1)
GOTO End_Func
END IF
ELSE
FEED$ = g_SOURCEFILE$
END IF
LET g_CURFILE$ = MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1)
' Initialize
gtk_window_set_title(g_Progress, CONCAT$("Converting '", MID$(FEED$, INSTRREV(FEED$, "/")+1), "'"))
' Only when not in TEST mode
IF dialog > 0 THEN
totallines = gtk_text_buffer_get_line_count(nbook[gtk_notebook_get_current_page(g_Notebook)].buffer)
gtk_widget_show_all(g_Progress):SYNC
END IF
LET total$ = ""
LET g_COUNTER = 1
' Read source program
OPEN FEED$ FOR READING AS g_SOURCEFILE
WHILE NOT(ENDFILE(g_SOURCEFILE)) DO
' Update progressbar
gtk_progress_bar_set_text(g_Progressbar, CONCAT$("Parsing line ", STR$( g_COUNTER)) )
IF dialog > 0 THEN
gtk_progress_bar_set_fraction(g_Progressbar, (double)(g_COUNTER-1)/totallines)
SYNC
END IF
READLN line$ FROM g_SOURCEFILE
' Line is not empty?
IF NOT(ENDFILE(g_SOURCEFILE)) AND LEN(line$) > 0 THEN
IF EQUAL(RIGHT$(line$, 2), " \\") AND NOT(EQUAL(LEFT$(line$, 3), "REM")) AND NOT(EQUAL(LEFT$(line$, 1), CHR$(39))) THEN
total$ = CONCAT$(total$, LEFT$(line$, LEN(line$) - 2))
ELSE
WRITELN "/* noparse ", FEED$, " BACON LINE ", g_COUNTER, " */" TO g_HFILE
WRITELN "/* noparse ", FEED$, " BACON LINE ", g_COUNTER, " */" TO g_CFILE
total$ = CHOP$(CONCAT$(total$, line$))
IF NOT(EQUAL(LEFT$(total$, 3), "REM")) AND NOT(EQUAL( LEFT$(total$, 1), CHR$(39) )) THEN
Tokenize(total$)
END IF
LET total$ = ""
END IF
IF g_PARSE_STATUS THEN BREAK
ENDIF
INCR g_COUNTER
WEND
CLOSE FILE g_SOURCEFILE
' Check if enclosed IF/ELIF/ELSE needs to be closed
IF g_IF_PARSE IS 1 THEN WRITELN "}" TO g_CFILE
' Finalize main C-file
WRITELN "__B2C__PROGRAM__EXIT:" TO g_CFILE
WRITELN "return 0;" TO g_CFILE
WRITELN "}" TO g_CFILE
' Finalize STRING ARRAY file for DATA
WRITELN " \"\" };" TO STRINGARRAYFILE
' Finalize FLOAT ARRAY file for DATA
WRITELN " 0.0};" TO FLOATARRAYFILE
' Include functions and subs
SPLIT CHOP$(g_INCLUDE_FILES$) BY " " TO incfiles$ SIZE dim
FOR i = 1 TO dim
IF LEN(incfiles$[i]) > 0 THEN WRITELN "#include \"", incfiles$[i], CHR$(34) TO g_HFILE
NEXT
' Close all filehandles
CLOSE FILE FLOATARRAYFILE
CLOSE FILE STRINGARRAYFILE
CLOSE FILE g_HFILE
CLOSE FILE g_CFILE
' Hide when error
IF g_PARSE_STATUS THEN
gtk_widget_hide(g_Progress):SYNC
GOTO End_Func
END IF
' Only when not in TEST mode
IF dialog > 0 THEN
gtk_progress_bar_set_text(g_Progressbar, "Conversion done!")
SLEEP 500:SYNC
gtk_widget_hide(g_Progress)
END IF
' Start indentation
IF ISTRUE(g_TMP_PRESERVE) AND dialog > 0 THEN
IF ISTRUE(LEN(EXEC$("which indent 2>/dev/null"))) THEN
SPLIT CHOP$(g_TMP_FILES$) BY " " TO tmpfiles$ SIZE dim
FOR i = 1 TO dim
IF NOT(REGEX(tmpfiles$[i], ".*\\.cpp")) THEN
IF ISTRUE(INSTR(OS$, "Darwin")) OR ISTRUE(INSTR(OS$, "BSD")) THEN
RENAME tmpfiles$[i] TO CONCAT$(tmpfiles$[i], ".BAK")
SYSTEM CONCAT$("indent ", tmpfiles$[i], ".BAK ", tmpfiles$[i])
DELETE FILE CONCAT$(tmpfiles$[i], ".BAK")
ELSE
SYSTEM CONCAT$("indent ", tmpfiles$[i])
DELETE FILE CONCAT$(tmpfiles$[i], "~")
END IF
END IF
NEXT i
Run_Dialog(GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, CONCAT$(NL$, "Indentation done."), -1)
ELSE
Run_Dialog(GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, "WARNING: 'indent' not found on this system!\n\nGenerated source code cannot be beautified.", -1)
END IF
END IF
' Check if we need to run xgettext
IF g_XGETTEXT AND dialog > 0 THEN
IF ISTRUE(LEN(EXEC$("which xgettext 2>/dev/null"))) THEN
SYSTEM CONCAT$("xgettext -d ", LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".")-1), " -s -o ", LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".")-1), ".pot ", g_TMP_FILES$)
IF NOT(FILEEXISTS(CONCAT$(LEFT$(g_SOURCEFILE$, INSTR(g_SOURCEFILE$, ".")-1), ".pot"))) THEN
Run_Dialog(GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, CONCAT$(NL$, "WARNING: catalog file not created!"), -1)
ELSE
Run_Dialog(GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, CONCAT$(NL$, "Extracting gettext strings done."), -1)
END IF
ELSE
Run_Dialog(GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, "WARNING: 'xgettext' not found on this system!", -1)
END IF
END IF
' Start compilation
IF ISFALSE(g_NO_COMPILE) OR dialog = 0 THEN
IF ISFALSE(LEN(EXEC$(CONCAT$("which ", g_CCNAME$, " 2>/dev/null")))) THEN
Run_Dialog(GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, CONCAT$("WARNING: '", g_CCNAME$, "' not found on this system!\n\nGenerated source code cannot be compiled."), -1)
GOTO End_Func
END IF
' Make sure GCC uses English localization
lang$ = GETENVIRON$("LANG")
SETENVIRON "LANG", "C"
gtk_widget_show_all(g_Compiling)
SLEEP 500: SYNC
SYSTEM CONCAT$(g_CCNAME$, " ", g_CCFLAGS$, " -o ", LEFT$(g_SOURCEFILE$, LEN(g_SOURCEFILE$) - 4), g_BINEXT$, " ", g_CFILE$, " ", LDFLAGS$, " > ", g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log 2>&1")
gtk_widget_hide(g_Compiling)
' Restore language
SETENVIRON "LANG", lang$
' Add temp file
g_TMP_FILES$ = CONCAT$(g_TMP_FILES$, " ", g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log")
IF ISFALSE(FILELEN(CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log"))) THEN
IF NOT(gtk_toggle_button_get_active(g_So_check)) AND dialog > 0 THEN
IF Run_Dialog(GTK_MESSAGE_INFO, GTK_BUTTONS_YES_NO, CONCAT$(NL$, "Program '", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/")+1, INSTRREV(g_SOURCEFILE$, ".")-INSTRREV(g_SOURCEFILE$, "/")-1), g_BINEXT$, "' ready. Execute?" ), -1) IS GTK_RESPONSE_YES THEN
gtk_widget_show_all(g_Execute)
ENDIF
ELIF dialog > 0 THEN
Run_Dialog(GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, CONCAT$(NL$, "Program '", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/")+1, INSTRREV(g_SOURCEFILE$, ".")-INSTRREV(g_SOURCEFILE$, "/")-1), g_BINEXT$, "' ready." ), -1)
ELSE
gtk_text_buffer_set_text(g_Test_buffer2, EXEC$(CONCAT$(g_TEMPDIR$, LEFT$(g_BACONSHELL$, INSTRREV(g_BACONSHELL$, ".")-1) )), -1)
END IF
ELSE
' Only print first error
OPEN CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log") FOR READING AS errlog
WHILE NOT(ENDFILE(errlog)) DO
READLN g_ERROR$ FROM errlog
IF (NOT(INSTR(g_ERROR$, "from ")) OR INSTR(g_ERROR$, "from") > INSTR(g_ERROR$, "error:")) AND REGEX(g_ERROR$, "[0-9]+") AND REGEX(g_ERROR$, "\\: error\\:") THEN
g_ERRORTXT$ = CONCAT$("Cause:", MID$(g_ERROR$, INSTR(g_ERROR$, "error:") + 6))
g_FILE_LINE$ = MID$(g_ERROR$, 1, INSTR(g_ERROR$, "error:") - 1)
BREAK
ELIF (NOT(INSTR(g_ERROR$, "from ")) OR INSTR(g_ERROR$, "from") > INSTR(g_ERROR$, "Error:")) AND REGEX(g_ERROR$, "[0-9]+") AND REGEX(g_ERROR$, "\\: Error\\:") THEN
g_ERRORTXT$ = CONCAT$("Cause:", MID$(g_ERROR$, INSTRREV(g_ERROR$, ":") + 1))
g_FILE_LINE$ = MID$(g_ERROR$, INSTR(g_ERROR$, "Error: ") + 7)
BREAK
ELIF (NOT(INSTR(g_ERROR$, "from ")) OR INSTR(g_ERROR$, "from") > INSTR(g_ERROR$, "warning:")) AND REGEX(g_ERROR$, "[0-9]+") AND REGEX(g_ERROR$, "\\: warning\\:") THEN
g_ERRORTXT$ = CONCAT$("Cause:", MID$(g_ERROR$, INSTR(g_ERROR$, "warning:") + 8))
g_FILE_LINE$ = MID$(g_ERROR$, 1, INSTR(g_ERROR$, "warning:") - 1)
BREAK
ELIF (NOT(INSTR(g_ERROR$, "from ")) OR INSTR(g_ERROR$, "from") > INSTR(g_ERROR$, ":")) AND REGEX(g_ERROR$, "[0-9]+\\:") THEN
g_ERRORTXT$ = CONCAT$("Cause:", 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$)) OR dialog = 0 THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, EXEC$(CONCAT$("cat ", g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".log")) ,-1)
ELSE
' Get the error string from the logfile
IF INSTR(g_FILE_LINE$, "line") THEN
g_LINE = VAL(MID$(g_FILE_LINE$, INSTR(g_FILE_LINE$, "line") + 4))
ELSE
g_LINE = VAL(MID$(g_FILE_LINE$, INSTR(g_FILE_LINE$, ":") + 1))
END IF
' Initiate error file name and error line in C code
g_FEED$ = MID$(g_FILE_LINE$, 1, INSTR(g_FILE_LINE$, ":")-1)
g_CURLINE$ = CONCAT$(STR$(g_LINE), " ")
g_COUNTER = 1
OPEN g_FILE$ FOR READING AS errlog
WHILE NOT(ENDFILE(errlog)) DO
READLN line$ FROM errlog
IF INSTR(line$, "BACON LINE") AND INSTR(line$, "noparse") THEN
g_CURLINE$ = MID$(line$, INSTR(line$, "BACON LINE") + 10)
g_FEED$ = MID$(line$, INSTR(line$, "noparse") + 7)
g_FEED$ = CHOP$(MID$(g_FEED$, 1, INSTR(g_FEED$, " BACON LINE")))
END IF
IF g_COUNTER IS g_LINE THEN
COUNTER = 1
OPEN g_FEED$ FOR READING AS g_SOURCEFILE
WHILE NOT(ENDFILE(g_SOURCEFILE)) DO
READLN line$ FROM g_SOURCEFILE
IF COUNTER IS VAL(MID$(g_CURLINE$, 1, INSTRREV(g_CURLINE$, " "))) THEN
Run_Dialog(GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, CONCAT$("File '", g_FEED$, "'", NL$, NL$, "Line ", STR$(COUNTER), ": ", CHOP$(line$), NL$, NL$, g_ERRORTXT$) , COUNTER)
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) OR dialog = 0 THEN
SPLIT CHOP$(g_TMP_FILES$) BY " " TO tmpfiles$ SIZE dim
FOR i = 1 TO dim
DELETE FILE tmpfiles$[i]
NEXT i
ELIF g_CPP IS 1 THEN
RENAME CONCAT$(g_SOURCEFILE$, ".cpp") TO CONCAT$(g_TEMPDIR$, "/", MID$(g_SOURCEFILE$, INSTRREV(g_SOURCEFILE$, "/") + 1), ".cpp")
END IF
LABEL End_Func
END SUB