dl-fldigi/src/config_script/script_parsing.cxx

2193 wiersze
72 KiB
C++

// ----------------------------------------------------------------------------
// 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 <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include <string.h>
#include "config.h"
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/stat.h>
#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:<br>
* 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:<br>
* 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:<br>
* 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:<br>
* 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:<br>
* 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:<br>
* 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<br> \< 0 = Error<br>
*****************************************************************/
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 <ENABLE|YES|1> or <DISABLE|NO|0>
* \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.<br>
* \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.<br>
* \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.<br>
* \param scriptCommand Script command string<br>
* \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.<br>
*****************************************************************/
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.<br>
*****************************************************************/
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<br> \< 0 = Error<br>
*****************************************************************/
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;
}