// ---------------------------------------------------------------------------- // Copyright (C) 2015 // Robert Stiles // // This file is part of fldigi // // fldigi is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // fldigi is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // ---------------------------------------------------------------------------- #include #include "config.h" #include "util.h" #include #include #include #include #include #include #include #include "debug.h" #include "gettext.h" #include "script_parsing.h" #include "run_script.h" // Do not use directly. It's copied for each instance static const SCRIPT_COMMANDS default_operator_command_table[] = { { CMD_CALLSIGN, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_callsign_info, 0, 0}, { CMD_NAME, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_name_info, 0, 0}, { CMD_QTH, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_qth_info, 0, 0}, { CMD_LOCATOR, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_locator_info, 0, 0}, { CMD_ANTENNA, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_antenna_info, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_audio_device_command_table[] = { { CMD_OSS_AUDIO, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_use_oss_audio_device, 0, 0}, { CMD_OSS_AUDIO_DEV_PATH, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_oss_audio_device_path, 0, 0}, { CMD_PORT_AUDIO, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_use_port_audio_device, 0, 0}, { CMD_PORTA_CAP, SCRIPT_COMMAND, 0, 2, {0}, { p_int, p_dev_name }, 0, 0, 0, process_capture_path, 0, 0}, { CMD_PORTA_PLAY, SCRIPT_COMMAND, 0, 2, {0}, { p_int, p_dev_name }, 0, 0, 0, process_playback_path, 0, 0}, { CMD_PULSEA, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_use_pulse_audio_device, 0, 0}, { CMD_PULSEA_SERVER, SCRIPT_COMMAND, 0, 1, {0}, { p_dev_path }, 0, 0, 0, process_pulse_audio_device_path, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_audio_settings_command_table[] = { { CMD_CAPTURE_SAMPLE_RATE, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_audio_device_sample_rate_capture, 0, 0}, { CMD_PLAYBACK_SAMPLE_RATE, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_audio_device_sample_rate_playback, 0, 0}, { CMD_AUDIO_CONVERTER, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_audio_device_converter, 0, 0}, { CMD_RX_PPM, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_rx_ppm, 0, 0}, { CMD_TX_PPM, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_tx_ppm, 0, 0}, { CMD_TX_OFFSET, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_tx_offset, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_audio_rt_channel_command_table[] = { { CMD_AUDIO_L_R, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_modem_signal_left_right, 0, 0}, { CMD_AUDIO_REV_L_R, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_reverse_left_right, 0, 0}, { CMD_PTT_RIGHT_CHAN, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_ptt_tone_right_channel, 0, 0}, { CMD_CW_QSK_RT_CHAN, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_cw_qsk_right_channel, 0, 0}, { CMD_PSEUDO_FSK_RT_CHAN, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_pseudo_fsk_right_channel, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_audio_wave_command_table[] = { { CMD_WAVE_SR, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_wave_file_sample_rate, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_rig_hrdwr_ptt_command_table[] = { { CMD_HPPT_PTT_RT, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hrdw_ptt_right_audio_channel, 0, 0}, { CMD_HPTT_SP2, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hrdw_ptt_sep_serial_port, 0, 0}, { CMD_HPTT_SP2_PATH, SCRIPT_COMMAND, 0, 1, {0}, { p_dev_path }, 0, 0, 0, process_hrdw_ptt_sep_serial_port_path, 0, 0}, { CMD_HPTT_SP2_RTS, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hrdw_ptt_sep_serial_port_rts, 0, 0}, { CMD_HPTT_SP2_DTR, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hrdw_ptt_sep_serial_port_dtr, 0, 0}, { CMD_HPTT_SP2_RTS_V, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hrdw_ptt_sep_serial_port_rts_v, 0, 0}, { CMD_HPTT_SP2_DTR_V, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hrdw_ptt_sep_serial_port_dtr_v, 0, 0}, { CMD_HPTT_SP2_START_DELAY, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_hrdw_ptt_start_delay, 0, 0}, { CMD_HPTT_SP2_END_DELAY, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_hrdw_ptt_end_delay, 0, 0}, { CMD_HPTT_UHROUTER, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hrdw_ptt_uhrouter, 0, 0}, { CMD_HPTT_SP2_INITIALIZE, SCRIPT_COMMAND, 0, 0, {0}, { p_void }, 0, 0, 0, process_hrdw_ptt_initialize, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_rigcat_command_table[] = { { CMD_RIGCAT_STATE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_use_rigcat, 0, 0}, { CMD_RIGCAT_DESC_FILE, SCRIPT_COMMAND, 0, 1, {0}, { p_filename }, 0, 0, 0, process_rigcat_desc_file, 0, 0}, { CMD_RIGCAT_DEV_PATH, SCRIPT_COMMAND, 0, 1, {0}, { p_dev_path }, 0, 0, 0, process_rigcat_device_path, 0, 0}, { CMD_RIGCAT_RETRIES, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_rigcat_retries, 0, 0}, { CMD_RIGCAT_RETRY_INTERVAL, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_rigcat_retry_interval, 0, 0}, { CMD_RIGCAT_WRITE_DELAY, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_rigcat_write_delay, 0, 0}, { CMD_RIGCAT_INTIAL_DELAY, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_rigcat_init_delay, 0, 0}, { CMD_RIGCAT_BAUD_RATE, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_rigcat_baud_rate, 0, 0}, { CMD_RIGCAT_STOP_BITS, SCRIPT_COMMAND, 0, 1, {0}, { p_float }, 0, 0, 0, process_rigcat_stop_bits, 0, 0}, { CMD_RIGCAT_ECHO, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_commands_echoed, 0, 0}, { CMD_RIGCAT_TOGGLE_RTS_PTT, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_toggle_rts_ptt, 0, 0}, { CMD_RIGCAT_RESTORE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_restore_on_close, 0, 0}, { CMD_RIGCAT_PTT_COMMAND, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_cat_command_ptt, 0, 0}, { CMD_RIGCAT_RTS_12V, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_rts_12v, 0, 0}, { CMD_RIGCAT_DTR_12V, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_dtr_12v, 0, 0}, { CMD_RIGCAT_HRDWR_FLOW, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_hrdwr_flow, 0, 0}, { CMD_RIGCAT_VSP, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rigcat_vsp_enable, 0, 0}, { CMD_RIGCAT_INITIALIZE, SCRIPT_COMMAND, 0, 0, {0}, { p_void }, 0, 0, 0, process_rigcat_initialize, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_hamlib_command_table[] = { { CMD_HAMLIB_STATE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_use_hamlib, 0, 0}, { CMD_HAMLIB_RIG, SCRIPT_COMMAND, 0, 1, {0}, { p_dev_name }, 0, 0, 0, process_hamlib_rig, 0, 0}, { CMD_HAMLIB_DEV_PATH, SCRIPT_COMMAND, 0, 1, {0}, { p_dev_path }, 0, 0, 0, process_hamlib_device_path, 0, 0}, { CMD_HAMLIB_RETRIES, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_hamlib_retries, 0, 0}, { CMD_HAMLIB_RETRY_INTERVAL, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_hamlib_retry_interval, 0, 0}, { CMD_HAMLIB_WRITE_DELAY, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_hamlib_write_delay, 0, 0}, { CMD_HAMLIB_POST_WRITE_DELAY, SCRIPT_COMMAND, 0, 1, {0}, { p_unsigned_int }, 0, 0, 0, process_hamlib_post_write_delay, 0, 0}, { CMD_HAMLIB_BAUD_RATE, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_hamlib_baud_rate, 0, 0}, { CMD_HAMLIB_STOP_BITS, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_hamlib_stop_bits, 0, 0}, { CMD_HAMLIB_SIDE_BAND, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_hamlib_sideband, 0, 0}, { CMD_HAMLIB_PTT_COMMAND, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hamlib_ptt_hl_command, 0, 0}, { CMD_HAMLIB_DTR_12V, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hamlib_dtr_12, 0, 0}, { CMD_HAMLIB_RTS_12V, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hamlib_rts_12, 0, 0}, { CMD_HAMLIB_HRDWR_FLOW, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hamlib_rts_cts_flow, 0, 0}, { CMD_HAMLIB_SFTWR_FLOW, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_hamlib_xon_xoff_flow, 0, 0}, { CMD_HAMLIB_ADV_CONFIG, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_hamlib_advanced_config, 0, 0}, { CMD_HAMLIB_INITIALIZE, SCRIPT_COMMAND, 0, 0, {0}, { p_void }, 0, 0, 0, process_hamlib_initialize, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_rc_xmlrpc_command_table[] = { { CMD_RC_XMLRPC_STATE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_use_xml_rpc, 0, 0}, { CMD_RC_XMLRPC_BW_DELAY, SCRIPT_COMMAND, 0, 1, {0}, { p_float }, 0, 0, 0, process_xml_rpc_mode_bw_delay, 0, 0}, { CMD_RC_XMLRPC_INITIALIZE, SCRIPT_COMMAND, 0, 0, {0}, { p_void }, 0, 0, 0, process_xml_rpc_initialize, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_kiss_command_table[] = { { CMD_IO_KISS_IPA, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_io_kiss_ip_address, 0, 0}, { CMD_IO_KISS_IOPN, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_io_kiss_io_port_no, 0, 0}, { CMD_IO_KISS_OPN, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_io_kiss_o_port_no, 0, 0}, { CMD_IO_KISS_DP, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_io_kiss_dual_port, 0, 0}, { CMD_IO_KISS_BUSY, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_io_kiss_busy_channel, 0, 0}, { CMD_IO_KISS_CONT, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_io_kiss_continue_after, 0, 0}, { CMD_IO_KISS_ATTEN, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_io_kiss_kpsql_atten, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_arq_command_table[] = { { CMD_IO_ARQ_IPA, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_io_arq_ip_address, 0, 0}, { CMD_IO_ARQ_IOPN, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_io_arq_io_port_no, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_xmlrpc_command_table[] = { { CMD_IO_XMLRPC_IPA, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_io_xmlrpc_ip_address, 0, 0}, { CMD_IO_XMLRPC_IOPN, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_io_xmlrpc_io_port_no, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_io_command_table[] = { { CMD_IO_LOCK, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_io_lock, 0, 0}, { CMD_IO_ACT_PORT, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_io_active_port, 0, 0}, { CMD_IO_AX25_DECODE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_io_ax25_decode, 0, 0}, { CMD_IO_CSMA, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_io_csma, 0, 0}, { CMD_IO_KISS, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_kiss_command_table, sizeof(default_kiss_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_IO_ARQ, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_arq_command_table, sizeof(default_arq_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_IO_XMLRPC, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_xmlrpc_command_table, sizeof(default_xmlrpc_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_fldigi_command_table[] = { { CMD_FLDIGI_FREQ, SCRIPT_COMMAND, 0, 1, {0}, { p_double }, 0, 0, 0, process_rig_freq, 0, 0}, { CMD_FLDIGI_MODE, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_rig_mode, 0, 0}, { CMD_FLDIGI_WFHZ, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_wf_hz_offset, 0, 0}, { CMD_FLDIGI_RXID, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rx_rsid, 0, 0}, { CMD_FLDIGI_TXID, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_tx_rsid, 0, 0}, { CMD_FLDIGI_SPOT, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_spot, 0, 0}, { CMD_FLDIGI_REV, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rev, 0, 0}, { CMD_FLDIGI_AFC, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_afc, 0, 0}, { CMD_FLDIGI_LOCK, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_lock, 0, 0}, { CMD_FLDIGI_SQL, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_sql, 0, 0}, { CMD_FLDIGI_KPSQL, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_kpsql, 0, 0}, { CMD_FLDIGI_MODEM, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_modem, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_nbems_command_table[] = { { CMD_NBEMS_FLMSG_PATH, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_misc_nbems_flmsg_path, 0, 0}, { CMD_NBEMS_TIMEOUT, SCRIPT_COMMAND, 0, 1, {0}, { p_double }, 0, 0, 0, process_misc_nbems_timeout, 0, 0}, { CMD_NBEMS_STATE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_misc_nbems_state, 0, 0}, { CMD_NBEMS_MSG, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_misc_nbems_open_msg, 0, 0}, { CMD_NBEMS_FLMSG, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_misc_nbems_open_flmsg, 0, 0}, { CMD_NBEMS_BRWSR, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_misc_nbems_open_brwsr, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_id_rsid_command_table[] = { { CMD_ID_RSID_NOTIFY, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_notify, 0, 0}, { CMD_ID_RSID_SRCH_BP, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_search_bp, 0, 0}, { CMD_ID_RSID_MARK_PREV, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_mark_prev, 0, 0}, { CMD_ID_RSID_DETECTOR, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_detector, 0, 0}, { CMD_ID_RSID_ALRT_DIALOG, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_alert_dialog, 0, 0}, { CMD_ID_RSID_TX_FREQ_LOCK, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_tx_freq_lock, 0, 0}, { CMD_ID_RSID_FREQ_CHANGE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_freq_change, 0, 0}, { CMD_ID_RSID_ALLOW_ERRORS, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_rsid_allow_errors, 0, 0}, { CMD_ID_RSID_SQL_OPEN, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_rsid_sql_open, 0, 0}, { CMD_ID_RSID_PRETONE, SCRIPT_COMMAND, 0, 1, {0}, { p_double }, 0, 0, 0, process_rsid_pretone, 0, 0}, { CMD_ID_RSID_END_XMT_ID, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_rsid_end_xmt_id, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_id_video_command_table[] = { { CMD_ID_VIDEO_TX_ID_MODE, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_video_tx_id_mode, 0, 0}, { CMD_ID_VIDEO_TX_VIDEO_TXT, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_video_tx_vid_txt, 0, 0}, { CMD_ID_VIDEO_TX_TXT_INP, SCRIPT_COMMAND, 0, 1, {0}, { p_string }, 0, 0, 0, process_video_txt_input, 0, 0}, { CMD_ID_VIDEO_SMALL_FONT, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_video_small_font, 0, 0}, { CMD_ID_VIDEO_500_HZ, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_video_500hz, 0, 0}, { CMD_ID_VIDEO_WIDTH_LIMIT, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_video_width_limit, 0, 0}, { CMD_ID_VIDEO_CHAR_ROW, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_rsid_char_per_row, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_id_cw_command_table[] = { { CMD_ID_CW_TX_CALLSIGN, SCRIPT_COMMAND, 0, 1, {0}, { p_bool }, 0, 0, 0, process_cw_callsign, 0, 0}, { CMD_ID_CW_SPEED, SCRIPT_COMMAND, 0, 1, {0}, { p_int }, 0, 0, 0, process_cw_speed, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_id_command_table[] = { { CMD_ID_RSID, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_id_rsid_command_table, sizeof(default_id_rsid_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_ID_VIDEO, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_id_video_command_table, sizeof(default_id_video_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_ID_CW, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_id_cw_command_table, sizeof(default_id_cw_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; static const SCRIPT_COMMANDS default_top_level_command_table[] = { { CMD_FLDIGI, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_fldigi_command_table, sizeof(default_fldigi_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_OPERATOR, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_operator_command_table, sizeof(default_operator_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_AUDIO_DEVICE, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_audio_device_command_table, sizeof(default_audio_device_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_AUDIO_SETTINGS, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_audio_settings_command_table, sizeof(default_audio_settings_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_AUDIO_RT_CHANNEL, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_audio_rt_channel_command_table, sizeof(default_audio_rt_channel_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_AUDIO_WAVE, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_audio_wave_command_table, sizeof(default_audio_wave_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_HRDWR_PTT, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_rig_hrdwr_ptt_command_table, sizeof(default_rig_hrdwr_ptt_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_RIGCAT, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_rigcat_command_table, sizeof(default_rigcat_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_HAMLIB, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_hamlib_command_table, sizeof(default_hamlib_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_RC_XMLRPC, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_rc_xmlrpc_command_table, sizeof(default_rc_xmlrpc_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_IO, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_io_command_table, sizeof(default_io_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_NBEMS, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_nbems_command_table, sizeof(default_nbems_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_ID, SCRIPT_COMMAND, 0, 0, {0}, { p_list }, 0, 0, 0, 0, (struct script_cmds *) &default_id_command_table, sizeof(default_id_command_table)/sizeof(SCRIPT_COMMANDS)}, { CMD_LOAD_MACRO, SCRIPT_COMMAND | SCRIPT_STRUCTURED_ONLY, 0, 3, {0}, { p_int, p_int, p_string }, 0, 0, 0, process_load_macro, 0, 0}, { CMD_END_CMD, SCRIPT_COMMAND, 0, 0, {0}, { p_list_end }, 0, 0, 0, 0, 0, 0}, { {0} } }; /** ************************************************************** * \brief Macro command requires special procesing. * \param cmd Pointer to matching struct script_cmds script * command. * \return SCRIPT_CODES error see \ref script_codes *****************************************************************/ SCRIPT_CODES ScriptParsing::sc_macros(struct script_cmds *cmd) { bool not_done = false; std::string temp; SCRIPT_CODES error = script_no_errors; int line_number_start = line_number; char *local_buffer = (char *)0; _macro_command.clear(); temp.clear(); std::string search_cmd; search_cmd.assign(CMD_END_CMD).append(":"); local_buffer = new char[MAX_READLINE_LENGTH]; if(!local_buffer) return script_memory_allocation_error; while(!not_done) { if(ferror(fd)) { error = script_file_read_error; break; } if(feof(fd)) { error = script_unexpected_eof; break; } memset(local_buffer, 0, MAX_READLINE_LENGTH); if (fgets(local_buffer, MAX_READLINE_LENGTH, fd)) line_number++; temp.assign(local_buffer); trim(temp); if(temp.find(search_cmd) == std::string::npos) _macro_command.append(local_buffer); else break; } int pos = _macro_command.length() - 1; bool lf_removed = false; // Remove the last new line in the macro command (script syntax requirement) if(pos > 1) { // Windows way if(_macro_command[pos-1] == '\r' && _macro_command[pos] == '\n') { _macro_command.erase(pos - 1, 2); lf_removed = true; } } if((lf_removed == false) && (pos > 0)) { // Unix/Linux/MacOSX way if(_macro_command[pos] == '\n') _macro_command.erase(pos, 1); } if(error == script_unexpected_eof) { LOG_INFO(_("Missing command %s after line %d"), search_cmd.c_str(), line_number_start); } delete [] local_buffer; return error; } /** ************************************************************** * \brief Used for initialization of the function vector table. * \param cmd Pointer to matching struct script_cmds script * command. * \return SCRIPT_CODES error see \ref script_codes *****************************************************************/ SCRIPT_CODES ScriptParsing::sc_dummy(struct script_cmds *cmd) { return script_no_errors; } /** ************************************************************** * \brief Convert error numbers into human readable form. * \param error_no Error number to convert. * \param ln The offending line number in the script file. * \param cmd The script command is question. * \return SCRIPT_CODES error see \ref script_codes *****************************************************************/ char * ScriptParsing::script_error_string(SCRIPT_CODES error_no, int ln, char *cmd) { char *es = (char *) ""; memset(error_buffer, 0, sizeof(error_buffer)); memset(error_cmd_buffer, 0, sizeof(error_cmd_buffer)); memset(error_string, 0, sizeof(error_string)); if(cmd) { strncpy(error_cmd_buffer, cmd, sizeof(error_cmd_buffer)-1); } if(error_no < 0) { _script_error_detected = true; } switch(error_no) { case script_command_not_found: es = (char *) _("Command Not Found"); break; case script_non_script_file: es = (char *) _("Not a script file/tag not found"); break; case script_parameter_error: es = (char *) _("Invalid parameter"); break; case script_function_parameter_error: es = (char *) _("Invalid function parameter (internal non-script error)"); break; case script_mismatched_quotes: es = (char *) _("Missing paired quotes (\")"); break; case script_general_error: es = (char *) _("General Error"); break; case script_no_errors: es = (char *) _("No Errors"); break; case script_char_match_not_found: es = (char *) _("Character searched not found"); break; case script_end_of_line_reached: es = (char *) _("End of line reached"); break; case script_file_not_found: es = (char *) _("File not found"); break; case script_path_not_found: es = (char *) _("Directory path not found"); break; case script_args_eol: es = (char *) _("Unexpected end of parameter (args[]) list found"); break; case script_param_check_eol: es = (char *) _("Unexpected end of parameter check list found"); break; case script_paramter_exceeds_length: es = (char *) _("Character count in args[] parameter exceeds expectations"); break; case script_memory_allocation_error: es = (char *) _("Memory Allocation Error (internal non-script error)"); break; case script_incorrectly_assigned_value: es = (char *) _("Passed parameter is not of the expected type."); break; case script_invalid_parameter: es = (char *) _("Parameter is not valid."); break; case script_command_seperator_missing: es = (char *) _("Command missing ':'."); break; case script_max_sub_script_reached: es = (char *) _("Maximum open subscripts reached."); break; case script_subscript_exec_fail: es = (char *) _("Subscript execution fail (internal)."); break; case script_device_path_not_found: es = (char *) _("Script device path not found."); break; case script_unexpected_eof: es = (char *) _("Unexpected end of file reached."); break; case script_file_read_error: es = (char *) _("File read error"); break; default: es = (char *) _("Undefined error"); } snprintf(error_buffer, sizeof(error_buffer)-1, _("Line: %d Error:%d %s (%s)"), ln, error_no, es, error_cmd_buffer); return error_buffer; } /** ************************************************************** * \brief Search for first occurrence of a non white space * \param data Data pointer to search. * \param limit Number of bytes in the data buffer. * \param error returned error code. * \return Pointer to character if found. Otherwise, return null * \par Note:
* The searched condition is ignored if the expected content is * encapsulated in quotes \(\"\"\). *****************************************************************/ char * ScriptParsing::skip_white_spaces(char * data, char * limit, SCRIPT_CODES &error) { char *cPtr = (char *) 0; if(!data || !limit) { error = script_function_parameter_error; return (char *)0; } for(cPtr = data; cPtr < limit; cPtr++) { if(*cPtr > ' ') { error = script_no_errors; return cPtr; } } error = script_end_of_line_reached; return (char *)0; // End of line reached. } /** ************************************************************** * \brief Search for the first occurrence on a non number. * \param data Data pointer to search. * \param limit Number of bytes in the data buffer. * \param error returned error code. * \return Pointer to character if found. Otherwise, return null * \par Note:
* The searched condition is ignored if the expected content is * encapsulated in quotes \(\"\"\). *****************************************************************/ char * ScriptParsing::skip_numbers(char * data, char * limit, SCRIPT_CODES &error) { char *cPtr = (char *) 0; int q_flag = 0; if(!data || !limit) { error = script_function_parameter_error; return (char *)0; } for(cPtr = data; cPtr < limit; cPtr++) { if(*cPtr == '"') // Check for encapsulated strings ("") q_flag++; if((q_flag & 0x1)) // Continue if string is encapsulated continue; if(!isdigit(*cPtr)) { error = script_no_errors; return cPtr; } } if(q_flag & 0x1) { error = script_mismatched_quotes; } else { error = script_end_of_line_reached; } return (char *)0; // End of line reached. } /** ************************************************************** * \brief Skip characters until either a number or white space is * found. * \param data Data pointer to search. * \param limit Number of bytes in the data buffer. * \param error returned error code. * \return Pointer to character if found. Otherwise, return null * \par Note:
* The searched condition is ignored if the expected content is * encapsulated in quotes \(\"\"\). *****************************************************************/ char * ScriptParsing::skip_characters(char * data, char * limit, SCRIPT_CODES &error) { char *cPtr = (char *) 0; int q_flag = 0; if(!data || !limit) { error = script_function_parameter_error; return (char *)0; } for(cPtr = data; cPtr < limit; cPtr++) { if(*cPtr == '"') // Check for encapsulated strings ("") q_flag++; if((q_flag & 0x1)) // Continue if string is encapsulated continue; if(isdigit(*cPtr) || *cPtr <= ' ') { error = script_no_errors; return cPtr; } } if(q_flag & 0x1) { error = script_mismatched_quotes; } else { error = script_end_of_line_reached; } return (char *)0; // End of line reached. } /** ************************************************************** * \brief Search for the first occurrence of a white space. * \param data Data pointer to search. * \param limit Number of bytes in the data buffer. * \param error returned error code. * \return Pointer to character if found. Otherwise, return null * \par Note:
* The searched condition is ignored if the expected content is * encapsulated in quotes \(\"\"\). *****************************************************************/ char * ScriptParsing::skip_alpha_numbers(char * data, char * limit, SCRIPT_CODES &error) { char *cPtr = (char *) 0; int q_flag = 0; if(!data || !limit) { error = script_function_parameter_error; return (char *)0; } for(cPtr = data; cPtr < limit; cPtr++) { if(*cPtr == '"') // Check for encapsulated strings ("") q_flag++; if((q_flag & 0x1)) // Continue if string is encapsulated continue; if(*cPtr <= ' ') { error = script_no_errors; return cPtr; } } if(q_flag & 0x1) { error = script_mismatched_quotes; } else { error = script_end_of_line_reached; } return (char *)0; // End of line reached. } /** ************************************************************** * \brief Search for first occurrence of 'character' * \param c Character to search for * \param data Pointer to Data to search for character in. * \param limit Number of bytes in the data buffer. * \param error returned error code. * \return Pointer to character if found. Otherwise, return null * \par Note:
* The searched condition is ignored if the expected content is * encapsulated in quotes \(\"\"\). *****************************************************************/ char * ScriptParsing::skip_to_character(char c, char * data, char * limit, SCRIPT_CODES &error) { char *cPtr = (char *) 0; int q_flag = 0; if(!data || !limit) { error = script_function_parameter_error; return (char *)0; } for(cPtr = data; cPtr < limit; cPtr++) { if(*cPtr == '"') // Check for encapsulated strings ("") q_flag++; if((q_flag & 0x1)) // Continue if string is encapsulated continue; if(*cPtr == c) { // Match found. Return pointer to it's location error = script_no_errors; return cPtr; } } if(q_flag & 0x1) { error = script_mismatched_quotes; } else { error = script_end_of_line_reached; } return (char *)0; // End of line reached. } /** ************************************************************** * \brief Replace CR, LF, and '#' with '0' (by value) * \param data Search data pointer * \param limit data buffer size * \return void (none) * \par Note:
* The searched condition is ignored if the remark character \(#\) * is encapsulated in quotes \(\"\"\). *****************************************************************/ SCRIPT_CODES ScriptParsing::remove_crlf_comments(char *data, char *limit, size_t &count) { char *cPtr = (char *) 0; int q_flag = 0; SCRIPT_CODES error = script_no_errors; if(!data || !limit) return script_function_parameter_error; count = 0; for(cPtr = data; cPtr < limit; cPtr++) { if(*cPtr == '\r' || *cPtr == '\n') { *cPtr = 0; return script_no_errors; } if(*cPtr == '"') q_flag++; if((q_flag & 0x1)) continue; if(*cPtr == '#') { *cPtr = 0; break; } if(*cPtr > ' ') count++; } // Remove trailing white spaces. while(cPtr >= data) { if(*cPtr <= ' ') *cPtr = 0; else break; cPtr--; } if(q_flag & 0x1) { error = script_mismatched_quotes; } else { error = script_end_of_line_reached; } return error; } /** ************************************************************** * \brief Copy memory from address to address. * \param buffer Destination buffer * \param sPtr Start of the copy Address * \param ePtr End of the copy Address * \param limit Destination buffer size * command. * \return SCRIPT_CODES error see \ref script_codes *****************************************************************/ SCRIPT_CODES ScriptParsing::copy_string_uppercase(char *buffer, char *sPtr, char *ePtr, size_t limit) { if(!buffer || !sPtr || !ePtr || limit < 1) { return script_function_parameter_error; } char *dPtr = buffer; size_t index = 0; for(index = 0; index < limit; index++) { *dPtr++ = toupper(*sPtr++); if(sPtr >= ePtr) break; } return script_no_errors; } /** ************************************************************** * \brief Parse the parameters and seperate into individual components. * \param s char pointer to the start of the string. * \param e char pointer to the end of the string. * \param matching_command pointer to the data strucure of the matching * command. See \ref SCRIPT_COMMANDS * \return SCRIPT_CODES error see \ref script_codes *****************************************************************/ SCRIPT_CODES ScriptParsing::parse_parameters(char *s, char *e, SCRIPT_COMMANDS *matching_command) { char *c = s; char *d = (char *)0; int index = 0; int parameter_count = matching_command->argc; int count = 0; long tmp = 0; SCRIPT_CODES error = script_no_errors; // Clear the old pointers. for(index = 0; index < MAX_CMD_PARAMETERS; index++) { matching_command->args[index] = (char *)0; } if(parameter_count > 0) { count = parameter_count - 1; for(index = 0; index < count; index++) { c = skip_white_spaces(c, e, error); if(error != script_no_errors) return script_parameter_error; d = skip_to_character(',', c, e, error); if(error != script_no_errors) return script_parameter_error; *d = 0; tmp = (long) (d - c); if(tmp > 0) trim(c, (size_t)(tmp)); matching_command->args[index] = c; c = d + 1; } c = skip_white_spaces(c, e, error); if(error) return error; d = skip_alpha_numbers(c, e, error); if(error) return error; *d = 0; tmp = (long) (d - c); if(tmp > 0) trim(c, (size_t)(tmp)); matching_command->args[index] = c; } #ifdef TESTING for(int i = 0; i < parameter_count; i++) if(matching_command->args[i]) printf("parameters %d (%s)\n", i, matching_command->args[i]); #endif error = check_parameters(matching_command); if(error != script_no_errors) return error; // If assigned then special processing is required. if(matching_command->func) error = (this->*matching_command->func)(matching_command); if(error) return error; return script_no_errors; } /** ************************************************************** * \brief Execute callback function. * \param cb_data Pointer for making a copy of the data to prevent * exterior alteration of source information. * \return 0 = No error
\< 0 = Error
*****************************************************************/ int ScriptParsing::call_callback(SCRIPT_COMMANDS *cb_data) { int argc = 0; int error = 0; int index = 0; SCRIPT_COMMANDS *tmp = (SCRIPT_COMMANDS *)0; size_t count = 0; if(!cb_data || !cb_data->cb) return -1; argc = cb_data->argc; tmp = new SCRIPT_COMMANDS; if(!tmp) return -1; memset(tmp, 0, sizeof(SCRIPT_COMMANDS)); for(index = 0; index < argc; index++) { if(cb_data->args[index]) { count = strnlen(cb_data->args[index], MAX_PARAMETER_LENGTH-1); tmp->args[index] = new char[count+1]; if(tmp->args[index]) { memset(tmp->args[index], 0, count+1); strncpy(tmp->args[index], cb_data->args[index], count); } else { error = -1; break; } } else break; } if(error > -1) { // Fill SCRIPT_COMMANDS (tmp) struct with useful data. tmp->flags = cb_data->flags; tmp->command_length = cb_data->command_length; tmp->argc = cb_data->argc; strncpy(tmp->command, cb_data->command, MAX_COMMAND_LENGTH); // Initialize with do nothing functions tmp->func = &ScriptParsing::sc_dummy; tmp->cb = callback_dummy; error = (*cb_data->cb)(this, tmp); } if(tmp) { for(index = 0; index < argc; index++) { if(tmp->args[index]) { delete [] tmp->args[index]; } } delete tmp; } return error; } /** ************************************************************** * \brief Parse a single line of data from the script file being read. * \param data Pointer the the script scring in question * \param buffer_size buffer size of the data pointer. * command. * \return SCRIPT_CODES error see \ref script_codes *****************************************************************/ SCRIPT_CODES ScriptParsing::parse_hierarchy_command(char *data, size_t buffer_size) { char *buffer = (char *)0; char *cPtr = (char *)0; char *endPtr = (char *)0; char *ePtr = (char *)0; int allocated_buffer_size = MAX_COMMAND_LENGTH; SCRIPT_CODES error = script_no_errors; SCRIPT_COMMANDS *local_list = _script_commands; size_t local_limit = _script_command_count; cPtr = data; endPtr = &data[buffer_size]; cPtr = skip_white_spaces(cPtr, endPtr, error); if(error != script_no_errors) return error; ePtr = skip_to_character(':', cPtr, endPtr, error); if(error != script_no_errors) return script_command_seperator_missing; buffer = new char [allocated_buffer_size]; if(!buffer) { LOG_INFO(_("Buffer allocation Error near File: %s Line %d"), __FILE__, __LINE__); return script_memory_allocation_error; } memset(buffer, 0, allocated_buffer_size); error = copy_string_uppercase(buffer, cPtr, ePtr, allocated_buffer_size-1); if(error != script_no_errors) { buffer[0] = 0; delete [] buffer; return error; } int str_count = str_cnt(buffer, allocated_buffer_size); trim(buffer, (size_t) str_count); char sub_command[MAX_COMMAND_LENGTH]; bool not_found = true; char *endCmd = ePtr; char *endCmdPtr = endPtr; cPtr = buffer; endPtr = &buffer[str_count]; while(not_found) { memset(sub_command, 0, sizeof(sub_command)); ePtr = skip_to_character('.', cPtr, endPtr, error); if(error == script_end_of_line_reached) { ePtr = endPtr; error = script_no_errors; } if(error == script_no_errors) { copy_string_uppercase(sub_command, cPtr, ePtr, MAX_COMMAND_LENGTH-1); cPtr = ePtr + 1; } else break; for(size_t i = 0; i < local_limit; i++) { if(local_list[i].command[0] == 0) { not_found = false; error = script_command_not_found; break; } if(strncmp(sub_command, local_list[i].command, MAX_COMMAND_LENGTH) == 0) { if((local_list[i].param_check[0] == p_list) && local_list[i].sub_commands) { local_limit = local_list[i].sub_command_count; local_list = local_list[i].sub_commands; break; } if((file_type() & local_list[i].flags) && !(SCRIPT_STRUCTURED_ONLY & local_list[i].flags)) { error = parse_parameters(++endCmd, endCmdPtr, &local_list[i]); if(error) { buffer[0] = 0; delete [] buffer; return error; } if(local_list[i].cb) { error = (SCRIPT_CODES) call_callback(&local_list[i]); if(error < script_no_errors) LOG_INFO(_("Call back for script command %s reported an Error"), local_list[local_limit].command); not_found = false; error = script_command_handled; break; } } else { LOG_INFO(_("Command %s ignored, dot notation not supported"), buffer); not_found = false; error = script_general_error; break; } } } } buffer[0] = 0; delete [] buffer; return error; } /** ************************************************************** * \brief Parse a single line of data from the script file being read. * \param data Pointer the the script scring in question * \param buffer_size buffer size of the data pointer. * command. * \return SCRIPT_CODES error see \ref script_codes *****************************************************************/ SCRIPT_CODES ScriptParsing::parse_single_command(FILE *fd, SCRIPT_COMMANDS *cur_list, size_t limit, char *data, size_t buffer_size) { char *buffer = (char *)0; char *cPtr = (char *)0; char *endPtr = (char *)0; char *ePtr = (char *)0; int allocated_buffer_size = MAX_COMMAND_LENGTH; size_t cmd_size = 0; size_t cmp_results = 0; size_t index = 0; size_t size = 0; bool dot_notation = false; SCRIPT_CODES error = script_no_errors; SCRIPT_COMMANDS *local_list = cur_list; size_t local_limit = limit; cPtr = data; endPtr = &data[buffer_size]; cPtr = skip_white_spaces(cPtr, endPtr, error); if(error != script_no_errors) return error; ePtr = skip_to_character(':', cPtr, endPtr, error); if(error != script_no_errors) return script_command_seperator_missing; buffer = new char [allocated_buffer_size]; if(!buffer) { LOG_INFO(_("Buffer allocation Error near File: %s Line %d"), __FILE__, __LINE__); return script_memory_allocation_error; } memset(buffer, 0, allocated_buffer_size); error = copy_string_uppercase(buffer, cPtr, ePtr, allocated_buffer_size-1); if(error != script_no_errors) { buffer[0] = 0; delete [] buffer; return error; } int str_count = (int) strnlen(buffer, allocated_buffer_size); trim(buffer, (size_t) str_count); for(int i = 0; i < str_count; i++) { if(buffer[i] == '.') { error = parse_hierarchy_command(data, buffer_size); if(error == script_no_errors) dot_notation = true; break; } } if(dot_notation == false && error == script_no_errors) { for(index = 0; index < local_limit; index++) { size = strnlen(local_list[index].command, MAX_COMMAND_LENGTH); cmd_size = strnlen(buffer, MAX_COMMAND_LENGTH); cmp_results = memcmp(buffer, local_list[index].command, size); if(cmp_results == 0 && (cmd_size == size)) { if(local_list[index].param_check[0] == p_list_end) { return script_end_of_list_reached; } if(local_list[index].sub_commands && local_list[index].param_check[0] == p_list) { if(recursive_count <= RECURSIVE_LIMIT) { read_file(fd, local_list[index].sub_commands, local_list[index].sub_command_count); } else { error = script_recursive_limit_reached; } break; } if((file_type() & local_list[index].flags) && !(SCRIPT_DOT_NOTATION_ONLY & local_list[index].flags)) { if(local_list[index].argc > 0) { error = parse_parameters(++ePtr, endPtr, &local_list[index]); if(error) { buffer[0] = 0; delete [] buffer; return error; } } if(local_list[index].cb) { error = (SCRIPT_CODES) call_callback(&local_list[index]); if(error < script_no_errors) LOG_INFO(_("Call back for script command %s reported an Error"), local_list[index].command); } } else { LOG_INFO(_("Command %s ignored, structured command not supported"), buffer); error = script_general_error; } break; } } } buffer[0] = 0; delete [] buffer; return error; } /** ************************************************************** * \brief Script entry point for parsing the script file. * \param file_name_path path and file name for the script to parse. * \return SCRIPT_CODES error see \ref script_codes *****************************************************************/ SCRIPT_CODES ScriptParsing::read_file(FILE *fd, SCRIPT_COMMANDS *cur_list, size_t limit) { SCRIPT_CODES return_code = script_no_errors; SCRIPT_COMMANDS *local_list = cur_list; size_t count = 0; bool errors_reported = false; recursive_count++; if(recursive_count > RECURSIVE_LIMIT) return script_recursive_limit_reached; while(1) { if(ferror(fd) || feof(fd)) break; memset(line_buffer, 0, sizeof(line_buffer)); if (fgets(line_buffer, sizeof(line_buffer) - 1, fd)) line_number++; #ifdef TESTING printf("Reading: %s", line_buffer); #endif return_code = remove_crlf_comments(line_buffer, &line_buffer[sizeof(line_buffer)], count); if(count < 1) { continue; } if(return_code >= script_no_errors) { return_code = parse_single_command(fd, local_list, limit, line_buffer, sizeof(line_buffer) - 1); } if(return_code == script_end_of_list_reached) break; if(return_code < script_no_errors) { LOG_INFO("%s", script_error_string(return_code, line_number, line_buffer)); errors_reported = true; } } recursive_count--; if(errors_reported) return script_errors_reported; return script_no_errors; } /** ************************************************************** * \brief Script entry point for parsing the script file. * \param file_name_path path and file name for the script to parse. * \return SCRIPT_CODES error see \ref script_codes *****************************************************************/ SCRIPT_CODES ScriptParsing::parse_commands(char *file_name_path) { char *cPtr = (char *)0; SCRIPT_CODES error_code = script_no_errors; size_t tmp = 0; SCRIPT_COMMANDS *local_script_commands = _script_commands; size_t local_script_command_count = _script_command_count; if(!file_name_path) { LOG_INFO(_("Invalid function parameter 'char *file_name_path' (null)")); return script_function_parameter_error; } fd = fopen(file_name_path, "r"); line_number = 0; if(!fd) { LOG_INFO(_("Unable to open file %s"), file_name_path); return script_file_not_found; } memset(line_buffer, 0, sizeof(line_buffer)); char *retval = fgets(line_buffer, sizeof(line_buffer) - 1, fd); line_number++; tmp = strlen(SCRIPT_FILE_TAG); line_buffer[tmp] = 0; tmp = strncmp(SCRIPT_FILE_TAG, line_buffer, tmp); if(!retval || tmp) { cPtr = script_error_string(script_non_script_file, line_number, line_buffer); LOG_INFO("%s", cPtr); fclose(fd); return script_non_script_file; } error_code = read_file(fd, local_script_commands, local_script_command_count); fclose(fd); return error_code; } /** ************************************************************** * \brief Assign a list of valid parameters for verification checks. * \param array An Array of pointers to each element. * \param array_count Number of entries in the array. * \return the array count or '0' if error. * \par Note: * This array is limited to the first parameter of the command * used in it's comparison. *****************************************************************/ int ScriptParsing::assign_valid_parameters(const char *command, const char **array, const int array_count) { if(!array || array_count < 1 || !command) return 0; int index = 0; int count = 0; SCRIPT_COMMANDS * cmd_sc = search_command(_script_commands, 0, command); if(!cmd_sc) { return 0; } for(index = 0; index < array_count; index++) { if(*array[index]) count++; } if(count != array_count) return 0; cmd_sc->valid_values = array; cmd_sc->valid_value_count = array_count; return array_count; } /** ************************************************************** * \brief Return true state if string is matched. * \param state Referenced value to assign results to. * \param string Pointer to the data string. * \param true_state Pointer to the data to match with. * \return SCRIPT_CODES error code. *****************************************************************/ inline SCRIPT_CODES ScriptParsing::test_on_off_state(bool &state, char *string, char *true_state=(char *)"ON") { if(!string || !true_state) { return script_function_parameter_error; } bool flag = false; if(strncmp(string, true_state, MAX_PARAMETER_LENGTH) == 0) flag = true; state = flag; return script_no_errors; } /** ************************************************************** * \brief Validate if file is located in the specified location. * \param filename Pointer to a series of charcters * \return SCRIPT_CODES error code. *****************************************************************/ SCRIPT_CODES ScriptParsing::check_filename(char *filename) { SCRIPT_CODES error = script_no_errors; if(!filename) { return script_function_parameter_error; } FILE *fd = (FILE *)0; fd = fopen(filename, "r"); if(!fd) { error = script_file_not_found; } else { fclose(fd); } return error; } /** ************************************************************** * \brief Validate if path is present. * \param path The path to verify. * \return SCRIPT_CODES error code. *****************************************************************/ SCRIPT_CODES ScriptParsing::check_path(const char *path) { if(!path) { return script_function_parameter_error; } struct stat st; memset(&st, 0, sizeof(struct stat)); if(stat(path, &st) == 0) { if(st.st_mode & S_IFDIR) return script_no_errors; } return script_path_not_found; } /** ************************************************************** * \brief Validate if device path is present. * \param path The path to verify. * \return SCRIPT_CODES error code. *****************************************************************/ SCRIPT_CODES ScriptParsing::check_dev_path(const char *path) { if(!path) { return script_function_parameter_error; } struct stat st; memset(&st, 0, sizeof(struct stat)); #ifdef __WIN32__ std::string alt_path; int value = 0; int cnt = 0; alt_path.assign(path); if(!alt_path.empty()) { if(alt_path.find("COM") != std::string::npos) { cnt = sscanf(alt_path.c_str(), "COM%d", &value); if(cnt && (value > 0)) return script_no_errors; } } #endif if(stat(path, &st) == 0) { if(st.st_mode & S_IFCHR) return script_no_errors; } return script_device_path_not_found; } /** ************************************************************** * \brief Validate bool representation. * \param value String data or * \param flag Depending on string content a value of true or false assigned * \return SCRIPT_CODES error code. *****************************************************************/ SCRIPT_CODES ScriptParsing::check_bool(const char *value, bool &flag) { if(!value) { return script_function_parameter_error; } flag = false; std::string uc_value; uc_value.assign(value); to_uppercase(uc_value); static char *bool_true_flags[] = { (char *)PARM_ENABLE, (char *)PARM_YES, (char *)_("1"), (char *)0 }; static char *bool_false_flags[] = { (char *) PARM_DISABLE, (char *)PARM_NO, (char *)_("0"), (char *)0 }; for(size_t i = 0; i < sizeof(bool_true_flags)/sizeof(char *); i++) { if(bool_true_flags[i] == (char *)0) break; if(strncmp(uc_value.c_str(), bool_true_flags[i], 7) == 0) { flag = true; return script_no_errors; } } for(size_t i = 0; i < sizeof(bool_false_flags)/sizeof(char *); i++) { if(bool_false_flags[i] == (char *)0) break; if(strncmp(uc_value.c_str(), bool_false_flags[i], 7) == 0) { flag = false; return script_no_errors; } } flag = false; return script_invalid_parameter; } /** ************************************************************** * \brief Validate if the parameter is a value. * \param value The string in question. * \param p format verification. * \return SCRIPT_CODES error code. *****************************************************************/ SCRIPT_CODES ScriptParsing::check_numbers(char *value, paramter_types p) { SCRIPT_CODES error = script_no_errors; size_t length = 0; size_t index = 0; int data_count = 0; int signed_value = 0; int decimal_point = 0; if(!value) return script_function_parameter_error; length = strnlen(value, MAX_PARAMETER_LENGTH); if(length < 1) return script_parameter_error; // Skip any leading white spaces. for(index = 0; index < length; index++) { if(value[index] > ' ') break; } if((index >= length)) return script_parameter_error; switch(p) { case p_int: case p_long: if(value[0] == '-' || value[0] == '+') { index++; signed_value++; } case p_unsigned_int: case p_unsigned_long: for(; index< length; index++) { if(isdigit(value[index])) data_count++; else break; } break; if(data_count) return script_no_errors; case p_float: case p_double: if(value[0] == '-' || value[0] == '+') { index++; signed_value++; } for(; index< length; index++) { if(isdigit(value[index])) data_count++; if(value[index] == '.') decimal_point++; if(decimal_point > 1) return script_parameter_error; } if(data_count) return script_no_errors; break; default:; } return error; } /** ************************************************************** * \brief Validate the script parameter(s) are of the expected format. * \param cmd Matching command data structure. * \param p A table of expected parameters types (null terminated). * \param p_count the number of 'p[]' items in the table (includes null termination). * \return SCRIPT_CODES error code. *****************************************************************/ SCRIPT_CODES ScriptParsing::check_parameters(struct script_cmds *cmd) { SCRIPT_CODES error = script_no_errors; int count = 0; int index = 0; size_t size = 0; bool flag = false; if(!cmd) return script_function_parameter_error; count = cmd->argc; if(count < 1) return script_no_errors; for(index = 0; index < count; index++) { if(!cmd->args[index]) { return script_args_eol; } if(cmd->param_check[index] == p_null) { size = 0; } else { size = strnlen(cmd->args[index], MAX_COMMAND_LENGTH); } switch(cmd->param_check[index]) { case p_null: error = script_param_check_eol; break; case p_char: if(size > 1) error = script_paramter_exceeds_length; break; case p_bool: error = check_bool(cmd->args[index], flag); break; case p_int: case p_long: case p_unsigned_int: case p_unsigned_long: case p_float: case p_double: error = check_numbers(cmd->args[index], cmd->param_check[index]); break; case p_dev_path: error = check_dev_path(cmd->args[index]); break; case p_dev_name: case p_string: if(size < 1) error = script_parameter_error; break; case p_path: error = check_path(cmd->args[index]); break; case p_filename: error = check_filename(cmd->args[index]); break; case p_list: case p_list_end: case p_void: break; } if(error != script_no_errors) break; } return error; } /** ************************************************************** * \brief Search the content of SCRIPT_COMMANDS structure table * for the specified command. * \param command The command to search for. * \return Pointer to the matching SCRIPT_COMMANDS entry. Null if * not found. *****************************************************************/ SCRIPT_COMMANDS * ScriptParsing::search_command(SCRIPT_COMMANDS * table, size_t limit, const char *command) { char *cmd_buffer = (char *)0; int diff = 0; SCRIPT_COMMANDS * found = (SCRIPT_COMMANDS *) 0; size_t count = limit; size_t index = 0; if(!command) return found; cmd_buffer = new char [MAX_COMMAND_LENGTH]; if(!cmd_buffer) { LOG_INFO(_("cmd_buffer allocation error near line %d"), __LINE__); return found; } memset(cmd_buffer, 0, MAX_COMMAND_LENGTH); strncpy(cmd_buffer, command, MAX_COMMAND_LENGTH-1); to_uppercase(cmd_buffer, (int) MAX_COMMAND_LENGTH); trim(cmd_buffer, (size_t) MAX_COMMAND_LENGTH); for(index = 0; index < count; index++) { diff = strncmp(cmd_buffer, table[index].command, MAX_COMMAND_LENGTH); if(diff == 0) { found = &table[index]; break; } } cmd_buffer[0] = 0; delete [] cmd_buffer; return found; } /** ************************************************************** * \brief Convert string to uppercase characters.
* \par str Pointer to data. * \par limit data buffer size * \return void *****************************************************************/ void ScriptParsing::to_uppercase(char *str, int limit) { if(!str || limit < 1) return; int character = 0; int count = 0; int index = 0; count = (int) strnlen(str, limit); for(index = 0; index < count; index++) { character = str[index]; if(character == 0) break; character = (char) toupper(character); str[index] = character; } } /** ************************************************************** * \brief Convert string to uppercase characters.
* \par str String storage passed by reference. * \return void *****************************************************************/ void ScriptParsing::to_uppercase(std::string &str) { int character = 0; int count = 0; int index = 0; count = (int) str.length(); for(index = 0; index < count; index++) { character = str[index]; if(character == 0) break; character = (char) toupper(character); str[index] = character; } } #if 0 /** ************************************************************** * \brief Assign Call back function to a given script command.
* \param scriptCommand Script command string
* \param cb Pointer to call back function. int (*cb)(ScriptParsing *sp, SCRIPT_COMMANDS *sc) *****************************************************************/ int ScriptParsing::assign_callback(const char *scriptCommand, int (*cb)(ScriptParsing *sp, SCRIPT_COMMANDS *sc)) { char *cmd_buffer = (char *)0; int diff = 0; size_t count = _script_command_count; size_t index = 0; if(!scriptCommand || !cb) return 0; cmd_buffer = new char[MAX_COMMAND_LENGTH]; if(!cmd_buffer) { LOG_INFO(_("cmd_buffer allocation error near line %d"), __LINE__); return 0; } memset(cmd_buffer, 0, MAX_COMMAND_LENGTH); strncpy(cmd_buffer, scriptCommand, MAX_COMMAND_LENGTH-1); to_uppercase(cmd_buffer, (int) MAX_COMMAND_LENGTH); trim(cmd_buffer, (size_t) MAX_COMMAND_LENGTH); for(index = 0; index < count; index++) { diff = strncmp(cmd_buffer, _script_commands[index].command, MAX_COMMAND_LENGTH); if(diff == 0) { if(_script_commands[index].cb) LOG_INFO(_("Over writing call back funcion for \"%s\""), cmd_buffer); _script_commands[index].cb = cb; break; } } cmd_buffer[0] = 0; delete [] cmd_buffer; return 0; } #endif // #if 0 /** ************************************************************** * \brief Assign member calling function to a command * \param top_command Top Command * \param sub_command Sub command * \param func Assigned calling function member * \return void (nothing) *****************************************************************/ SCRIPT_CODES ScriptParsing::assign_member_func(char *cmd, SCRIPT_CODES (ScriptParsing::*func)(struct script_cmds *)) { char *buffer = (char *)0; char *cPtr = (char *)0; char *endPtr = (char *)0; char *ePtr = (char *)0; int allocated_buffer_size = MAX_COMMAND_LENGTH; size_t size = 0; SCRIPT_CODES error = script_no_errors; SCRIPT_COMMANDS *local_list = _script_commands; size_t local_limit = _script_command_count; if(!cmd || !func) return script_invalid_parameter; size = strnlen(cmd, MAX_COMMAND_LENGTH); cPtr = cmd; endPtr = &cmd[size]; size = 0; cPtr = skip_white_spaces(cPtr, endPtr, error); if(error != script_no_errors) return error; ePtr = skip_to_character(':', cPtr, endPtr, error); if(error != script_no_errors) return script_command_seperator_missing; buffer = new char [allocated_buffer_size]; if(!buffer) { LOG_INFO(_("Buffer allocation Error near File: %s Line %d"), __FILE__, __LINE__); return script_memory_allocation_error; } memset(buffer, 0, allocated_buffer_size); error = copy_string_uppercase(buffer, cPtr, ePtr, allocated_buffer_size-1); if(error != script_no_errors) { buffer[0] = 0; delete [] buffer; return error; } int str_count = str_cnt(buffer, allocated_buffer_size); trim(buffer, (size_t) str_count); char sub_command[MAX_COMMAND_LENGTH]; bool not_found = true; cPtr = buffer; endPtr = &buffer[str_count]; while(not_found) { memset(sub_command, 0, sizeof(sub_command)); ePtr = skip_to_character('.', cPtr, endPtr, error); if(error == script_end_of_line_reached) { ePtr = endPtr; error = script_no_errors; } if(error == script_no_errors) { copy_string_uppercase(sub_command, cPtr, ePtr, MAX_COMMAND_LENGTH-1); cPtr = ePtr + 1; } else break; for(size_t i = 0; i < local_limit; i++) { if(local_list[i].command[0] == 0) { not_found = false; error = script_command_not_found; break; } if(strncmp(sub_command, local_list[i].command, MAX_COMMAND_LENGTH) == 0) { if((local_list[i].param_check[0] == p_list) && local_list[i].sub_commands) { local_limit = local_list[i].sub_command_count; local_list = local_list[i].sub_commands; break; } local_list[i].func = func; local_list[i].command_length = strnlen(local_list[i].command, MAX_COMMAND_LENGTH); not_found = false; error = script_no_errors; break; } } } buffer[0] = 0; delete [] buffer; return error; } #if 0 /** ************************************************************** * \brief Assign member calling function to a command * \param top_command Top Command * \param sub_command Sub command * \param func Assigned calling function member * \return void (nothing) *****************************************************************/ void ScriptParsing::assign_member_func(char *cmd, SCRIPT_CODES (ScriptParsing::*func)(struct script_cmds *)) { if(!top_command || !func) return; SCRIPT_COMMANDS *top_table = (SCRIPT_COMMANDS *)0; SCRIPT_COMMANDS *modify_table = (SCRIPT_COMMANDS *)0; if(top_cache) { if(strncmp(top_cache->command, top_command, MAX_COMMAND_LENGTH) == 0) { top_table = top_cache; } } if(!top_table) { for(int i = 0; i < _script_command_count; i++) { if(strncmp(_script_commands[i].command, top_command, MAX_COMMAND_LENGTH) == 0) { top_cache = &_script_commands[i]; top_table = top_cache; break; } } } if(!top_table) return; if(!sub_command) modify_table = top_table; if(modify_table == (SCRIPT_COMMANDS *)0) { if(top_table->sub_commands) { for(int i = 0; i < top_table->sub_command_count; i++) { if(strncmp(sub_command, top_table->sub_commands[i].command, MAX_COMMAND_LENGTH) == 0) { modify_table = &top_table->sub_commands[i]; break; } } } } if(modify_table != (SCRIPT_COMMANDS *)0) { modify_table->func = func; modify_table->command_length = strnlen(modify_table->command, MAX_COMMAND_LENGTH); } } #endif // #if 0 /** ************************************************************** * \brief Initialize variables * \return void (nothing) *****************************************************************/ void ScriptParsing::clear_script_parameters(bool all) { _path.clear(); _file_type = SCRIPT_COMMAND; _macro_command.clear(); } /** ************************************************************** * \brief Initialize callable members. * \return void (nothing) *****************************************************************/ void ScriptParsing::initialize_function_members(void) { std::string cmd; cmd.assign(CMD_LOAD_MACRO).append(":"); // For localization assign_member_func((char *) cmd.c_str(), &ScriptParsing::sc_macros); } /** ************************************************************** * \brief Copy environment to the sub ScriptParsing class * \param src Source Class pointer to copy from. *****************************************************************/ int ScriptParsing::CopyScriptParsingEnv(ScriptParsing *src) { if(!src || (src == this)) return -1; parent(src); script_commands(src->script_commands()); script_command_count(src->script_command_count()); initialize_function_members(); return 0; } /** ************************************************************** * \brief Constructor: Copy and initialize.
*****************************************************************/ int ScriptParsing::copy_tables(struct script_cmds * subcmds, size_t count) { size_t index = 0; size_t table_count = 0; SCRIPT_COMMANDS * dst_table = 0; SCRIPT_COMMANDS * src_table = 0; recursive_count++; if(recursive_count > RECURSIVE_LIMIT) return 0; for(index = 0; index < count; index++) { src_table = subcmds[index].sub_commands; table_count = subcmds[index].sub_command_count; if(src_table && table_count) { dst_table = new SCRIPT_COMMANDS[table_count]; if(dst_table) { add_to_delete_list(dst_table); memcpy(dst_table, src_table, sizeof(SCRIPT_COMMANDS) * table_count); subcmds[index].sub_commands = dst_table; subcmds[index].sub_command_count = table_count; copy_tables(dst_table, table_count); } } } recursive_count--; return 0; } /** ************************************************************** * \brief Constructor: Copy and initialize function arrays.
*****************************************************************/ ScriptParsing::ScriptParsing() { size_t count = 0; clear_script_parameters(true); memset(line_buffer, 0, sizeof(line_buffer)); memset(error_cmd_buffer, 0, sizeof(error_cmd_buffer)); memset(error_string, 0, sizeof(error_string)); memset(error_buffer, 0, sizeof(error_buffer)); memset(memory_delete_list, 0, sizeof(memory_delete_list)); delete_list_count = 0; top_cache = 0; recursive_count = 0; _script_error_detected = false; _restart_flag = false; fd = 0; count = sizeof(default_top_level_command_table)/sizeof(SCRIPT_COMMANDS); _script_commands = new SCRIPT_COMMANDS[count]; if(_script_commands) { add_to_delete_list(_script_commands); _script_command_count = count; memcpy(_script_commands, default_top_level_command_table, sizeof(SCRIPT_COMMANDS) * _script_command_count); copy_tables(_script_commands, _script_command_count); } recursive_count = 0; initialize_function_members(); } /** ************************************************************** * \brief Destructor *****************************************************************/ ScriptParsing::~ScriptParsing() { int index = 0; for(index = 0; index < MAX_DELETE_LIST_COUNT; index++) { if(memory_delete_list[index]) { delete [] memory_delete_list[index]; } } } /** ************************************************************** * \brief Keep track of memory allocation for easy deallocation. *****************************************************************/ void ScriptParsing::add_to_delete_list(SCRIPT_COMMANDS *ptr) { if(!ptr) return; if(delete_list_count < MAX_DELETE_LIST_COUNT) { memory_delete_list[delete_list_count] = ptr; delete_list_count++; } } /** ************************************************************** * \brief Dummy callback function for initialization of * function pointers. * \param sp The calling ScriptParsing Class * \param sc Command data structure pointer to the matching script * command. * \return 0 = No error
\< 0 = Error
*****************************************************************/ int callback_dummy(ScriptParsing *sp, struct script_cmds *sc) { return 0; } /** ******************************************************** * \brief Determine the length of the string with a count * limitation. * \return signed integer. The number of characters in the * array not to excede count limit. ***********************************************************/ int ScriptParsing::str_cnt(char * str, int count_limit) { if(!str || (count_limit < 1)) return 0; int value = 0; for(int index = 0; index < count_limit; index++) { if(str[index] == 0) break; value++; } return value; } /** ******************************************************** * \brief Trim leading and trailing spaces from string. * \param s String to modify * \return s modified string. ***********************************************************/ std::string &ScriptParsing::trim(std::string &s) { char *buffer = (char *)0; char *dst = (char *)0; char *end = (char *)0; char *src = (char *)0; long count = s.size(); buffer = new char[count + 1]; if(!buffer) return s; memcpy(buffer, s.c_str(), count); buffer[count] = 0; dst = src = buffer; end = &buffer[count]; while(src < end) { if(*src > ' ') break; src++; } if(src > dst) { while((dst < end) && (src < end)) *dst++ = *src++; *dst = 0; } while(end >= buffer) { if(*end > ' ') break; *end-- = 0; } s.assign(buffer); delete [] buffer; return s; } /** ************************************************************** * \brief Remove leading/trailing white spaces and quotes. * \param buffer Destination buffer * \param limit passed buffer size * \return void *****************************************************************/ void ScriptParsing::trim(char *buffer, size_t limit) { char *s = (char *)0; char *e = (char *)0; char *dst = (char *)0; size_t count = 0; if(!buffer || limit < 1) { return; } for(count = 0; count < limit; count++) if(buffer[count] == 0) break; if(count < 1) return; s = buffer; e = &buffer[count-1]; for(size_t i = 0; i < count; i++) { if((*s <= ' ') || (*s == '"')) s++; else break; } while(e > s) { if(*e == '"') { *e-- = 0; break; } if(*e > ' ') break; if(*e <= ' ') *e = 0; e--; } dst = buffer; while(s <= e) { *dst++ = *s++; } *dst = 0; }