diff options
-rw-r--r-- | device-functions.c | 78 | ||||
-rw-r--r-- | error_utils.c | 1004 | ||||
-rw-r--r-- | lcd.c | 616 | ||||
-rw-r--r-- | lcd.h | 14 | ||||
-rw-r--r-- | parser.c | 2022 | ||||
-rw-r--r-- | string_utils.c | 96 |
6 files changed, 1915 insertions, 1915 deletions
diff --git a/device-functions.c b/device-functions.c index 9422b40..ac2acfb 100644 --- a/device-functions.c +++ b/device-functions.c @@ -1,39 +1,39 @@ -#include "device-functions.h"
-
-/* START FUNCTION DESCRIPTION ********************************************
-Set_frequency <DEVFUNC.LIB>
-
-SYNTAX: Set_frequency(int check_possible_only,int word_override,int range_override,int channel,float set_freq)
-
-KEYWORDS:
-
-DESCRIPTION: sets the offset DAC.
-
-RETURN VALUE: error code (zero = OK).
-END DESCRIPTION **********************************************************/
-
-/*----------------------------------------------------------------------------------------------------------*/
-int Set_frequency(int check_possible_only,int word_override,int range_override,int channel,float set_freq)
-{
- // keep, but ignore, the first 3 parameters for now
-
- // all this does right now is check the frequency range,
- // and store the set value.
-
- /* abandon if high channel selected by user but not enabled by firmware */
- if (channel && !globals.Flash.ChanKey_frequency) {
- return InvalidChannel;
- }
-
- if (set_freq < 1.0) {
- return freq_lower_limit;
- }
- if (set_freq > 1.0e6) {
- return freq_upper_limit;
- }
-
- globals.ChannelState[channel].frequency=set_freq;
-
- return OK;
-}
-
+#include "device-functions.h" + +/* START FUNCTION DESCRIPTION ******************************************** +Set_frequency <DEVFUNC.LIB> + +SYNTAX: Set_frequency(int check_possible_only,int word_override,int range_override,int channel,float set_freq) + +KEYWORDS: + +DESCRIPTION: sets the offset DAC. + +RETURN VALUE: error code (zero = OK). +END DESCRIPTION **********************************************************/ + +/*----------------------------------------------------------------------------------------------------------*/ +int Set_frequency(int check_possible_only,int word_override,int range_override,int channel,float set_freq) +{ + // keep, but ignore, the first 3 parameters for now + + // all this does right now is check the frequency range, + // and store the set value. + + /* abandon if high channel selected by user but not enabled by firmware */ + if (channel && !globals.Flash.ChanKey_frequency) { + return InvalidChannel; + } + + if (set_freq < 1.0) { + return freq_lower_limit; + } + if (set_freq > 1.0e6) { + return freq_upper_limit; + } + + globals.ChannelState[channel].frequency=set_freq; + + return OK; +} + diff --git a/error_utils.c b/error_utils.c index 73d2999..c4eae61 100644 --- a/error_utils.c +++ b/error_utils.c @@ -1,502 +1,502 @@ -/* START LIBRARY DESCRIPTION *********************************************
-ERRCHK.LIB
- Copyright (c) 2006, Avtech Electrosystems Ltd.
-
-DESCRIPTION:
- Error-checking and reporting functions.
-
-SUPPORT LIB'S:
-END DESCRIPTION **********************************************************/
-
-
-/*** BeginHeader Error_check */
-
-#include <string.h>
-#include <glib/gprintf.h>
-#include "globals.h"
-#include "dummy_functions.h"
-#include "lcd.h"
-
-/*** EndHeader */
-
-/* FIXME */
-int Error_Screen=NO;
-
-void set_gpib_error_flags (int error_num);
-
-void set_gpib_error_flags (int error_num)
-{
-
- if (error_num == OK) {
- return;
- }
-
- /* set the error flags in the GPIB ESR register right away */
- switch (error_num) {
- case AsyncModeDisabled:
- case Unrecognized:
- case SyntaxError:
- case UnknownUnits:
- case InvalidChannel:
- GPIB_Set_Command_Error();
- break;
- case query_error_interrupted:
- case query_error_unterminated:
- GPIB_Set_Query_Error();
- break;
- case Overload_Detected:
- case Overtemp_Detected:
- case Overvolt_Detected:
- case Device_Specific_Aux_Error_Detected:
- case queue_overflow:
- case CalibrationPercentError:
- case CalibrationZeroError:
- case CalibrationMinMaxError:
- case CalibrationClosenessError:
- case CalibrationRangeError:
- case CalibrationPolarityError:
- case Soft_Limit_Exceeded:
- case SelfCalError:
- GPIB_Set_Device_Dependent_Error();
- break;
- default:
- GPIB_Set_Execution_Error();
- break;
- }
-
- return;
-}
-
-void queue_error(int error_num);
-
-void queue_error(int error_num)
-{
- if (error_num == OK) {
- return;
- }
-
- set_gpib_error_flags (error_num);
- if (globals.number_of_errors<error_queue_length) {
- ++globals.number_of_errors;
- globals.error_queue[globals.number_of_errors]=error_num;
- } else {
- globals.error_queue[globals.number_of_errors]=queue_overflow;
- }
-
- return;
-}
-
-
-
-/*----------------------------------------------------------------------------------------------------------*/
-void queue_error_and_get_text(gchar** response, int error_num)
-{
- g_assert (*response == NULL);
-
- if (error_num == OK) {
- return;
- }
- queue_error (error_num);
- get_error_text (response, error_num);
- return;
-}
-
-/*----------------------------------------------------------------------------------------------------------*/
-void queue_error_from_parser(gchar** response, int error_num)
-{
- g_assert (*response == NULL);
-
- if (error_num == OK) {
- return;
- }
- queue_error_and_get_text(response, error_num);
- Menu_Refresh();
- return;
-}
-
-
-void queue_error_for_gpib_only(int error_num);
-
-void queue_error_for_gpib_only(int error_num)
-{
-// not part of this project, but left in for coder's reference. Can be deleted for now
- if (error_num == OK) {
- return;
- }
- queue_error(error_num);
- return;
-}
-
-
-void queue_error_and_display_on_LCD(int error_num);
-
-void queue_error_and_display_on_LCD(int error_num)
-{
- gchar* response = NULL;
- queue_error_and_get_text(&response, error_num);
- LCD_display_error_message (response);
-}
-
-
-void queue_and_broadcast_sensor_alarm(int error_num);
-
-void queue_and_broadcast_sensor_alarm(int error_num)
-{
-// not part of this project, but left in for coder's reference. Can be deleted for now
-}
-
-/*----------------------------------------------------------------------------------------------------------*/
-void Error_Remove_From_Queue(void)
-{
- int i;
- for (i=1; i<globals.number_of_errors; ++i) {
- globals.error_queue[i]=globals.error_queue[i+1];
- }
- --globals.number_of_errors; /* error reported, so remove it from the error queue */
-}
-
-
-void format_error_text (gchar **response, int error_type, char *in);
-
-void format_error_text (gchar **response, int error_type, char *in)
-{
- char* prefix = NULL;
-
- switch (error_type) {
- case 0:
- prefix = g_strdup("No error");
- break;
- case -100:
- prefix=g_strdup("Command error");
- break;
- case -102:
- prefix=g_strdup("Syntax error");
- break;
- case -114:
- prefix=g_strdup("Command error");
- break;
- case -131:
- prefix=g_strdup("Invalid suffix");
- break;
- case -200:
- prefix=g_strdup("Execution error");
- break;
- case -221:
- prefix=g_strdup("Settings conflict");
- break;
- case -222:
- prefix=g_strdup("Data out of range");
- break;
- case -224:
- prefix=g_strdup("Illegal parameter value");
- break;
- case -240:
- prefix=g_strdup("Hardware error");
- break;
- case -300:
- prefix=g_strdup("Device-specific error");
- break;
- case -340:
- prefix=g_strdup("Calibration failed");
- break;
- case -350:
- prefix=g_strdup("Queue overflow");
- break;
- case -400:
- prefix=g_strdup("Query error");
- break;
- default:
- prefix=g_strdup("System error");
- break;
- }
-
-
- *response = g_strdup_printf("%d, \"%s; %s\"", error_type, prefix, in);
- g_free(prefix);
-}
-
-
-void get_error_text(gchar **response, int error_num)
-{
- switch (error_num) {
-
- case OK:
- format_error_text(response,0,"");
- break;
-
- case Unrecognized:
- format_error_text(response,-102,"Unrecognized command.");
- break;
-
- case AsyncModeDisabled:
- format_error_text(response,-102,"Async gating not available.");
- break;
-
- case SyntaxError:
- format_error_text(response,-100,"Recognized command, but improper syntax.");
- break;
-
- case InvalidChannel:
- format_error_text(response,-114,"Invalid channel suffix.");
- break;
-
- case OutOfRange:
- format_error_text(response,-222,"Too high or too low.");
- break;
-
- case Negative_Not_Allowed:
- format_error_text(response,-222,"Negative value not allowed.");
- break;
-
- case IllegalParameter:
- case amplitude_confined_values:
- format_error_text(response,-224,"Not in list of allowed values.");
- break;
-
- case UnknownUnits:
- format_error_text(response,-131,"Unrecognized units.");
- break;
-
- case Route_Range_Error:
- format_error_text(response,-224,"Ranges are not supported.");
- break;
-
- case AB_Mode_Error:
- format_error_text(response,-221,"This PW mode is not valid for the current trigger mode.");
- break;
-
- case Valid_For_RS232_TELNET_Only:
- format_error_text(response,-221,"Command valid in RS232 or TELNET modes only.");
- break;
-
- case PW_Exceeds_Period:
- format_error_text(response,-221,"PW can not exceed period.");
- break;
-
- case Delay_Exceeds_95Period:
- format_error_text(response,-221,"Delay can not exceed 95% of period.");
- break;
-
- case NeedNonZeroAmpl:
- format_error_text(response,-222,"Amplitude must be non-zero.");
- break;
-
- case freq_lower_limit:
- format_error_text(response,-222,"PRF too low.");
- break;
-
- case freq_upper_limit:
- format_error_text(response,-222,"PRF too high.");
- break;
-
- case pw_lower_limit:
- format_error_text(response,-222,"PW too low.");
- break;
-
- case pw_upper_limit:
- format_error_text(response,-222,"PW too high.");
- break;
-
- case max_rise_time_error:
- format_error_text(response,-222,"Rise time too high.");
- break;
-
- case min_rise_time_error:
- format_error_text(response,-222,"Rise time too low.");
- break;
-
- case max_slew_error:
- format_error_text(response,-222,"Slew rate too high.");
- break;
-
- case min_slew_error:
- format_error_text(response,-222,"Slew rate too low.");
- break;
-
- case max_load_type_error:
- format_error_text(response,-222,"Resistance too high.");
- break;
-
- case min_load_type_error:
- format_error_text(response,-222,"Duty cycle too high or load resistance too low.");
- break;
-
- case max_soft_current_limit_error:
- format_error_text(response,-222,"Current limit too high.");
- break;
-
- case min_soft_current_limit_error:
- format_error_text(response,-222,"Current limit too low.");
- break;
-
- case duty_cycle_upper_limit:
- format_error_text(response,-222,"Duty cycle too high.");
- break;
-
- case Average_Amplitude_Too_High:
- format_error_text(response,-222,"Average amplitude too high.");
- break;
-
- case delay_lower_limit:
- format_error_text(response,-222,"Delay too low.");
- break;
-
- case delay_upper_limit:
- format_error_text(response,-222,"Delay too high.");
- break;
-
- case amplitude_lower_limit:
- format_error_text(response,-222,"Amplitude too low.");
- break;
-
- case amplitude_upper_limit:
- format_error_text(response,-222,"Amplitude too high.");
- break;
-
- case peak_power_limit:
- format_error_text(response,-222,"Peak power too high.");
- break;
-
- case average_power_limit:
- format_error_text(response,-222,"Average power too high.");
- break;
-
- case offset_lower_limit:
- format_error_text(response,-222,"Offset too low.");
- break;
-
- case offset_upper_limit:
- format_error_text(response,-222,"Offset too high.");
- break;
-
- case ampl_plus_os_lower_limit:
- format_error_text(response,-222,"AMPL+OS too low.");
- break;
-
- case ampl_plus_os_upper_limit:
- format_error_text(response,-222,"AMPL+OS too high.");
- break;
-
- case DutyTriggerError:
- format_error_text(response,-221,"Duty cycle can not be set. Set PW instead.");
- break;
-
- case PW_Exceeds_Double_Separation:
- format_error_text(response,-221,"PW can not exceed double pulse separation.");
- break;
-
- case Double_Separation_Too_Large:
- format_error_text(response,-221,"Double pulse separation is too high. It must be < 95% of the period.");
- break;
-
- case queue_overflow:
- format_error_text(response,-350,"Clear with *cls or syst:err.");
- break;
-
- case query_error_interrupted:
- format_error_text(response,-400,"Data lost in output buffer.");
- break;
-
- case query_error_unterminated:
- format_error_text(response,-400,"No data to send.");
- break;
-
- case Overload_Detected:
- format_error_text(response,-300,"Power supply overload detected. The output has been turned off.");
- break;
-
- case Overtemp_Detected:
- format_error_text(response,-300,"Overheating problem. The output has been turned off.");
- break;
-
- case Overvolt_Detected:
- format_error_text(response,-300,"Over-voltage or over-current! The output has been turned off.");
- break;
-
- case Soft_Limit_Exceeded:
- format_error_text(response,-300,"Monitor current limit exceeded! The output has been turned off.");
- break;
-
- case Device_Specific_Aux_Error_Detected:
- // replace with "FIXME" if Flash not implemented yet
- format_error_text(response,-300,globals.Flash.aux_error_message);
- break;
-
- case CalibrationPercentError:
- format_error_text(response,-340,"Percent change is too large.");
- break;
-
- case CalibrationPolarityError:
- format_error_text(response,-340,"Old and new polarities disagree.");
- break;
-
- case CalibrationZeroError:
- format_error_text(response,-340,"Zero point can not be changed.");
- break;
-
- case CalibrationMinMaxError:
- format_error_text(response,-340,"Would prevent operation at the minimum or maximum settings.");
- break;
-
- case CalibrationClosenessError:
- format_error_text(response,-340,"Too few calibration points, or they are too closely spaced.");
- break;
-
- case CalibrationRangeError:
- format_error_text(response,-340,"Top or bottom of range. Can not be deleted.");
- break;
-
- case SelfCalError:
- format_error_text(response,-340,"Calibration problem.");
- break;
-
- case HardwareError:
- format_error_text(response,-240,"Not possible with the current calibration settings.");
- break;
-
- case CalibrationTimingProblem:
- format_error_text(response,-221,"Set timing to allow operation at minimum and maximum amplitudes.");
- break;
-
- case Coupled_OS_Ampl_Error:
- format_error_text(response,-221,"If ampl > 0, ampl+offset must be > 0, if ampl < 0, ampl+offset must be < 0.");
- break;
-
- case PW_Distort_Error:
- format_error_text(response,-240,"Not possible with the current PW distortion settings.");
- break;
-
- case burst_duty_error:
- format_error_text(response,-222,"Duty cycle inside burst is too high.");
- break;
-
- case min_burst_period_error:
- format_error_text(response,-222,"Time between consecutive rising edges inside burst is too low.");
- break;
-
- case max_burst_count_error:
- format_error_text(response,-222,"Too many pulses per burst.");
- break;
-
- case min_burst_gap_error:
- format_error_text(response,-222,"Pulse separation too low.");
- break;
-
- case max_burst_gap_error:
- format_error_text(response,-222,"Pulse separation too high.");
- break;
-
- case Burst_Exceeds_Period:
- format_error_text(response,-222,"Burst width can not exceed period.");
- break;
-
- case password_change_error:
- format_error_text(response,-222,"Incorrect old password, or new password is too long or short. ");
- break;
-
- default:
- format_error_text(response,-200,"Specific problem unknown.");
- }
-
-}
-
+/* START LIBRARY DESCRIPTION ********************************************* +ERRCHK.LIB + Copyright (c) 2006, Avtech Electrosystems Ltd. + +DESCRIPTION: + Error-checking and reporting functions. + +SUPPORT LIB'S: +END DESCRIPTION **********************************************************/ + + +/*** BeginHeader Error_check */ + +#include <string.h> +#include <glib/gprintf.h> +#include "globals.h" +#include "dummy_functions.h" +#include "lcd.h" + +/*** EndHeader */ + +/* FIXME */ +int Error_Screen=NO; + +void set_gpib_error_flags (int error_num); + +void set_gpib_error_flags (int error_num) +{ + + if (error_num == OK) { + return; + } + + /* set the error flags in the GPIB ESR register right away */ + switch (error_num) { + case AsyncModeDisabled: + case Unrecognized: + case SyntaxError: + case UnknownUnits: + case InvalidChannel: + GPIB_Set_Command_Error(); + break; + case query_error_interrupted: + case query_error_unterminated: + GPIB_Set_Query_Error(); + break; + case Overload_Detected: + case Overtemp_Detected: + case Overvolt_Detected: + case Device_Specific_Aux_Error_Detected: + case queue_overflow: + case CalibrationPercentError: + case CalibrationZeroError: + case CalibrationMinMaxError: + case CalibrationClosenessError: + case CalibrationRangeError: + case CalibrationPolarityError: + case Soft_Limit_Exceeded: + case SelfCalError: + GPIB_Set_Device_Dependent_Error(); + break; + default: + GPIB_Set_Execution_Error(); + break; + } + + return; +} + +void queue_error(int error_num); + +void queue_error(int error_num) +{ + if (error_num == OK) { + return; + } + + set_gpib_error_flags (error_num); + if (globals.number_of_errors<error_queue_length) { + ++globals.number_of_errors; + globals.error_queue[globals.number_of_errors]=error_num; + } else { + globals.error_queue[globals.number_of_errors]=queue_overflow; + } + + return; +} + + + +/*----------------------------------------------------------------------------------------------------------*/ +void queue_error_and_get_text(gchar** response, int error_num) +{ + g_assert (*response == NULL); + + if (error_num == OK) { + return; + } + queue_error (error_num); + get_error_text (response, error_num); + return; +} + +/*----------------------------------------------------------------------------------------------------------*/ +void queue_error_from_parser(gchar** response, int error_num) +{ + g_assert (*response == NULL); + + if (error_num == OK) { + return; + } + queue_error_and_get_text(response, error_num); + Menu_Refresh(); + return; +} + + +void queue_error_for_gpib_only(int error_num); + +void queue_error_for_gpib_only(int error_num) +{ +// not part of this project, but left in for coder's reference. Can be deleted for now + if (error_num == OK) { + return; + } + queue_error(error_num); + return; +} + + +void queue_error_and_display_on_LCD(int error_num); + +void queue_error_and_display_on_LCD(int error_num) +{ + gchar* response = NULL; + queue_error_and_get_text(&response, error_num); + LCD_display_error_message (response); +} + + +void queue_and_broadcast_sensor_alarm(int error_num); + +void queue_and_broadcast_sensor_alarm(int error_num) +{ +// not part of this project, but left in for coder's reference. Can be deleted for now +} + +/*----------------------------------------------------------------------------------------------------------*/ +void Error_Remove_From_Queue(void) +{ + int i; + for (i=1; i<globals.number_of_errors; ++i) { + globals.error_queue[i]=globals.error_queue[i+1]; + } + --globals.number_of_errors; /* error reported, so remove it from the error queue */ +} + + +void format_error_text (gchar **response, int error_type, char *in); + +void format_error_text (gchar **response, int error_type, char *in) +{ + char* prefix = NULL; + + switch (error_type) { + case 0: + prefix = g_strdup("No error"); + break; + case -100: + prefix=g_strdup("Command error"); + break; + case -102: + prefix=g_strdup("Syntax error"); + break; + case -114: + prefix=g_strdup("Command error"); + break; + case -131: + prefix=g_strdup("Invalid suffix"); + break; + case -200: + prefix=g_strdup("Execution error"); + break; + case -221: + prefix=g_strdup("Settings conflict"); + break; + case -222: + prefix=g_strdup("Data out of range"); + break; + case -224: + prefix=g_strdup("Illegal parameter value"); + break; + case -240: + prefix=g_strdup("Hardware error"); + break; + case -300: + prefix=g_strdup("Device-specific error"); + break; + case -340: + prefix=g_strdup("Calibration failed"); + break; + case -350: + prefix=g_strdup("Queue overflow"); + break; + case -400: + prefix=g_strdup("Query error"); + break; + default: + prefix=g_strdup("System error"); + break; + } + + + *response = g_strdup_printf("%d, \"%s; %s\"", error_type, prefix, in); + g_free(prefix); +} + + +void get_error_text(gchar **response, int error_num) +{ + switch (error_num) { + + case OK: + format_error_text(response,0,""); + break; + + case Unrecognized: + format_error_text(response,-102,"Unrecognized command."); + break; + + case AsyncModeDisabled: + format_error_text(response,-102,"Async gating not available."); + break; + + case SyntaxError: + format_error_text(response,-100,"Recognized command, but improper syntax."); + break; + + case InvalidChannel: + format_error_text(response,-114,"Invalid channel suffix."); + break; + + case OutOfRange: + format_error_text(response,-222,"Too high or too low."); + break; + + case Negative_Not_Allowed: + format_error_text(response,-222,"Negative value not allowed."); + break; + + case IllegalParameter: + case amplitude_confined_values: + format_error_text(response,-224,"Not in list of allowed values."); + break; + + case UnknownUnits: + format_error_text(response,-131,"Unrecognized units."); + break; + + case Route_Range_Error: + format_error_text(response,-224,"Ranges are not supported."); + break; + + case AB_Mode_Error: + format_error_text(response,-221,"This PW mode is not valid for the current trigger mode."); + break; + + case Valid_For_RS232_TELNET_Only: + format_error_text(response,-221,"Command valid in RS232 or TELNET modes only."); + break; + + case PW_Exceeds_Period: + format_error_text(response,-221,"PW can not exceed period."); + break; + + case Delay_Exceeds_95Period: + format_error_text(response,-221,"Delay can not exceed 95% of period."); + break; + + case NeedNonZeroAmpl: + format_error_text(response,-222,"Amplitude must be non-zero."); + break; + + case freq_lower_limit: + format_error_text(response,-222,"PRF too low."); + break; + + case freq_upper_limit: + format_error_text(response,-222,"PRF too high."); + break; + + case pw_lower_limit: + format_error_text(response,-222,"PW too low."); + break; + + case pw_upper_limit: + format_error_text(response,-222,"PW too high."); + break; + + case max_rise_time_error: + format_error_text(response,-222,"Rise time too high."); + break; + + case min_rise_time_error: + format_error_text(response,-222,"Rise time too low."); + break; + + case max_slew_error: + format_error_text(response,-222,"Slew rate too high."); + break; + + case min_slew_error: + format_error_text(response,-222,"Slew rate too low."); + break; + + case max_load_type_error: + format_error_text(response,-222,"Resistance too high."); + break; + + case min_load_type_error: + format_error_text(response,-222,"Duty cycle too high or load resistance too low."); + break; + + case max_soft_current_limit_error: + format_error_text(response,-222,"Current limit too high."); + break; + + case min_soft_current_limit_error: + format_error_text(response,-222,"Current limit too low."); + break; + + case duty_cycle_upper_limit: + format_error_text(response,-222,"Duty cycle too high."); + break; + + case Average_Amplitude_Too_High: + format_error_text(response,-222,"Average amplitude too high."); + break; + + case delay_lower_limit: + format_error_text(response,-222,"Delay too low."); + break; + + case delay_upper_limit: + format_error_text(response,-222,"Delay too high."); + break; + + case amplitude_lower_limit: + format_error_text(response,-222,"Amplitude too low."); + break; + + case amplitude_upper_limit: + format_error_text(response,-222,"Amplitude too high."); + break; + + case peak_power_limit: + format_error_text(response,-222,"Peak power too high."); + break; + + case average_power_limit: + format_error_text(response,-222,"Average power too high."); + break; + + case offset_lower_limit: + format_error_text(response,-222,"Offset too low."); + break; + + case offset_upper_limit: + format_error_text(response,-222,"Offset too high."); + break; + + case ampl_plus_os_lower_limit: + format_error_text(response,-222,"AMPL+OS too low."); + break; + + case ampl_plus_os_upper_limit: + format_error_text(response,-222,"AMPL+OS too high."); + break; + + case DutyTriggerError: + format_error_text(response,-221,"Duty cycle can not be set. Set PW instead."); + break; + + case PW_Exceeds_Double_Separation: + format_error_text(response,-221,"PW can not exceed double pulse separation."); + break; + + case Double_Separation_Too_Large: + format_error_text(response,-221,"Double pulse separation is too high. It must be < 95% of the period."); + break; + + case queue_overflow: + format_error_text(response,-350,"Clear with *cls or syst:err."); + break; + + case query_error_interrupted: + format_error_text(response,-400,"Data lost in output buffer."); + break; + + case query_error_unterminated: + format_error_text(response,-400,"No data to send."); + break; + + case Overload_Detected: + format_error_text(response,-300,"Power supply overload detected. The output has been turned off."); + break; + + case Overtemp_Detected: + format_error_text(response,-300,"Overheating problem. The output has been turned off."); + break; + + case Overvolt_Detected: + format_error_text(response,-300,"Over-voltage or over-current! The output has been turned off."); + break; + + case Soft_Limit_Exceeded: + format_error_text(response,-300,"Monitor current limit exceeded! The output has been turned off."); + break; + + case Device_Specific_Aux_Error_Detected: + // replace with "FIXME" if Flash not implemented yet + format_error_text(response,-300,globals.Flash.aux_error_message); + break; + + case CalibrationPercentError: + format_error_text(response,-340,"Percent change is too large."); + break; + + case CalibrationPolarityError: + format_error_text(response,-340,"Old and new polarities disagree."); + break; + + case CalibrationZeroError: + format_error_text(response,-340,"Zero point can not be changed."); + break; + + case CalibrationMinMaxError: + format_error_text(response,-340,"Would prevent operation at the minimum or maximum settings."); + break; + + case CalibrationClosenessError: + format_error_text(response,-340,"Too few calibration points, or they are too closely spaced."); + break; + + case CalibrationRangeError: + format_error_text(response,-340,"Top or bottom of range. Can not be deleted."); + break; + + case SelfCalError: + format_error_text(response,-340,"Calibration problem."); + break; + + case HardwareError: + format_error_text(response,-240,"Not possible with the current calibration settings."); + break; + + case CalibrationTimingProblem: + format_error_text(response,-221,"Set timing to allow operation at minimum and maximum amplitudes."); + break; + + case Coupled_OS_Ampl_Error: + format_error_text(response,-221,"If ampl > 0, ampl+offset must be > 0, if ampl < 0, ampl+offset must be < 0."); + break; + + case PW_Distort_Error: + format_error_text(response,-240,"Not possible with the current PW distortion settings."); + break; + + case burst_duty_error: + format_error_text(response,-222,"Duty cycle inside burst is too high."); + break; + + case min_burst_period_error: + format_error_text(response,-222,"Time between consecutive rising edges inside burst is too low."); + break; + + case max_burst_count_error: + format_error_text(response,-222,"Too many pulses per burst."); + break; + + case min_burst_gap_error: + format_error_text(response,-222,"Pulse separation too low."); + break; + + case max_burst_gap_error: + format_error_text(response,-222,"Pulse separation too high."); + break; + + case Burst_Exceeds_Period: + format_error_text(response,-222,"Burst width can not exceed period."); + break; + + case password_change_error: + format_error_text(response,-222,"Incorrect old password, or new password is too long or short. "); + break; + + default: + format_error_text(response,-200,"Specific problem unknown."); + } + +} + @@ -1,308 +1,308 @@ -#include "i2c.h"
-#include "lcd.h"
-#include <glib.h>
-#include <string.h>
-#include <stdlib.h>
-
-#define LCD_ENABLE 0x03 /* the 4x40 LCDs have two enable lines - 0x03 enables both at the same time */
-#define LCD_DATA_RAM 128 /* display RAM, in the LCD ICs */
-#define LCD_CG_RAM 64 /* custom character RAM, in the LCD ICs */
-
-#define LCD_chars_total 160
-#define LCD_cols 40
-#define LCD_rows 4 /* 4x40 LCD */
-
-char LCD_Data[LCD_rows][LCD_cols]; /* shadow copy of LCD display in local RAM, to minimize slow I2C writes */
-
-/*** EndHeader */
-
-
-static void break_up_string (char *in_string, int N, char **str1, char **str2, char **str3)
-{
-
-#define SUBSTRING_CNT 3
-
- int input_length;
- int j, k, copypos;
- int n;
-
- char *copy_input;
- char *p;
-
- j=k=copypos=0;
- input_length=strlen(in_string);
- copy_input = g_strdup(in_string);
-
- for (j=0; j<SUBSTRING_CNT; j++) {
-
- gchar *interm_str = g_strnfill (N, 0);
-
- for (k=0; k<N; k++) {
- copypos++; // next symbol
- if (copypos>input_length) {
- break;
- }
- if ((*(copy_input+k)==' ')&&(copypos<input_length)) { // space found
- //find next space
- p=strchr(copy_input+k+1,' ');
- if (p!=NULL) {
- // next space is beyond N char limit for one line
- if((p-copy_input)/sizeof(char)>=N) {
- break;
- }
- } else {
- // No more spaces. Does the last chunk of text fit?
- if (strlen(copy_input+k+1)>N-k) {
- break;
- }
- }
- }
- // valid character, copy to output string
- *(interm_str+k)=*(copy_input+k);
-
- }
- // remove processed part from the input
- if (copypos<=input_length) {
- strcpy(copy_input, in_string+copypos);
- }
- n = strlen(interm_str);
- for ((k=n-1); (k=0); k--) { //trim space
- if (*(interm_str+k)==' ') {
- *(interm_str+k)=0;
- } else {
- break;
- }
- }
- switch (j) {
- case 0:
- *str1 = g_strdup(interm_str);
- break;
- case 1:
- *str2 = g_strdup(interm_str);
- break;
- case 2:
- *str3 = g_strdup(interm_str);
- break;
- }
- g_free(interm_str);
-
- }
-
- g_free(copy_input);
-}
-
-
-
-
-void LCD_clear()
-{
- int i;
- int j;
-
- I2C_Write(PCF8574A+LCD_Port, 0x00 | LCD_ENABLE);
- I2C_Write(PCF8574A+LCD_Port, 0x00);
- I2C_Write(PCF8574A+LCD_Port, 0x10 | LCD_ENABLE);
- I2C_Write(PCF8574A+LCD_Port, 0x10);
-
- /* wait 1.64ms */
- g_usleep(1640);
-
- for (i=0; i<4; ++i)
- for (j=0; j<40; ++j) {
- LCD_Data[i][j]=0;
- }
-
- return;
-}
-
-
-static void LCD_RAM_write(int RAM_start,int row, int col, char *LCD_string)
-{
- /* rows: 0-3, cols: 0-39 */
-
-#define data_level 0x04
-
- int i;
- int cur_row, cur_col;
- int String_length;
- char char_out, enable_one_lcd;
- int ram_location;
- char last_op_a_write;
-
- if (!LCD_string) {
- return;
- }
-
- String_length=strlen(LCD_string);
- enable_one_lcd=0x02;
-
- last_op_a_write=0;
- cur_row=row;
- cur_col=col;
-
- if (cur_row<2) {
- enable_one_lcd=0x02;
- } else {
- enable_one_lcd=0x01;
- }
-
- /* write out the string */
- for (i=0; i<String_length; ++i) {
- if (cur_row<2) {
- enable_one_lcd=0x02;
- } else {
- enable_one_lcd=0x01;
- }
-
- if (LCD_string[i]!=LCD_Data[cur_row][cur_col]) {
- if (!last_op_a_write) {
- /* move to new position */
- ram_location = (cur_row & 1) * 64 + cur_col + RAM_start;
- char_out=ram_location & 0xf0;
- I2C_Write(PCF8574A+LCD_Port, char_out | enable_one_lcd);
- I2C_Write(PCF8574A+LCD_Port, char_out);
- char_out=ram_location << 4;
- I2C_Write(PCF8574A+LCD_Port, char_out | enable_one_lcd);
- I2C_Write(PCF8574A+LCD_Port, char_out);
- }
- LCD_Data[cur_row][cur_col]=LCD_string[i];
- char_out=LCD_string[i] & 0xf0;
- I2C_Write(PCF8574A+LCD_Port, char_out | enable_one_lcd | data_level);
- I2C_Write(PCF8574A+LCD_Port, char_out | data_level);
- char_out=LCD_string[i] << 4;
- I2C_Write(PCF8574A+LCD_Port, char_out | enable_one_lcd | data_level);
- I2C_Write(PCF8574A+LCD_Port, char_out | data_level);
- last_op_a_write=1;
- } else {
- last_op_a_write=0;
- }
-
- ++cur_col;
- if (cur_col==40) {
- cur_col=0;
- ++cur_row;
- }
- }
- return;
-}
-
-
-void LCD_write(int row, int col, char *LCD_string)
-{
- LCD_RAM_write(LCD_DATA_RAM, row, col, LCD_string);
- return;
-}
-
-
-static void LCD_make_custom_chars()
-{
- /* define custom LCD characters 2 and 3 (up arrow and down arrow).*/
- /* The up arrow is stored in one LCD controller (for rows 0 and 1) */
- /* The down arrow is stored in the other LCD controller (for rows 2 and 3) */
- LCD_RAM_write(LCD_CG_RAM,0,16,"\x4");
- LCD_RAM_write(LCD_CG_RAM,0,17,"\xe");
- LCD_RAM_write(LCD_CG_RAM,0,18,"\x15");
- LCD_RAM_write(LCD_CG_RAM,0,19,"\x4");
- LCD_RAM_write(LCD_CG_RAM,0,20,"\x4");
- LCD_RAM_write(LCD_CG_RAM,0,21,"\x4");
- LCD_RAM_write(LCD_CG_RAM,0,22,"\x4");
- LCD_RAM_write(LCD_CG_RAM,0,23,"\x4");
- LCD_RAM_write(LCD_CG_RAM,2,24,"\x4");
- LCD_RAM_write(LCD_CG_RAM,2,25,"\x4");
- LCD_RAM_write(LCD_CG_RAM,2,26,"\x4");
- LCD_RAM_write(LCD_CG_RAM,2,27,"\x4");
- LCD_RAM_write(LCD_CG_RAM,2,28,"\x4");
- LCD_RAM_write(LCD_CG_RAM,2,29,"\x15");
- LCD_RAM_write(LCD_CG_RAM,2,30,"\xe");
- LCD_RAM_write(LCD_CG_RAM,2,31,"\x4");
-// prove that it works - debug only
-// LCD_RAM_write(LCD_DATA_RAM,0,39,"\x2");
-// LCD_RAM_write(LCD_DATA_RAM,3,39,"\x3");
-
- return;
-}
-
-
-void LCD_initialize(void)
-{
- /* Wait 15ms */
- g_usleep(15000);
-
- I2C_Write(PCF8574A+LCD_Port, 0x30 | LCD_ENABLE);
- I2C_Write(PCF8574A+LCD_Port, 0x30);
-
- /* wait 4.1ms */
- g_usleep(4100);
-
- I2C_Write(PCF8574A+LCD_Port, 0x30 | LCD_ENABLE);
- I2C_Write(PCF8574A+LCD_Port, 0x30);
-
- /* wait 100us */
- g_usleep(100);
-
- I2C_Write(PCF8574A+LCD_Port, 0x30 | LCD_ENABLE);
- I2C_Write(PCF8574A+LCD_Port, 0x30);
-
- /* wait 4.1ms */
- g_usleep(4100);
-
- I2C_Write(PCF8574A+LCD_Port, 0x20 | LCD_ENABLE);
- I2C_Write(PCF8574A+LCD_Port, 0x20);
-
- /*wait 40us */
- g_usleep(40);
-
- I2C_Write(PCF8574A+LCD_Port, 0x20 | LCD_ENABLE);
- I2C_Write(PCF8574A+LCD_Port, 0x20);
- I2C_Write(PCF8574A+LCD_Port, 0x80 | LCD_ENABLE);
- I2C_Write(PCF8574A+LCD_Port, 0x80);
-
- /* wait 40us */
- g_usleep(40);
-
- LCD_clear();
-
- I2C_Write(PCF8574A+LCD_Port, 0x00 | LCD_ENABLE);
- I2C_Write(PCF8574A+LCD_Port, 0x00);
- I2C_Write(PCF8574A+LCD_Port, 0x60 | LCD_ENABLE);
- I2C_Write(PCF8574A+LCD_Port, 0x60);
-
- /* wait 40us */
- g_usleep(40);
-
- I2C_Write(PCF8574A+LCD_Port, 0x00 | LCD_ENABLE);
- I2C_Write(PCF8574A+LCD_Port, 0x00);
- I2C_Write(PCF8574A+LCD_Port, 0xc0 | LCD_ENABLE);
- I2C_Write(PCF8574A+LCD_Port, 0xc0);
-
- LCD_make_custom_chars();
-
- return;
-}
-
-
-void LCD_display_error_message(char *response)
-{
- char *row0 = NULL;
- char *row1 = NULL;
- char *row2 = NULL;
-
-// Error_Screen=1; //FIXME
-
- break_up_string (response, LCD_cols, &row0, &row1, &row2);
-
- LCD_clear();
- LCD_write(0,0,row0);
- LCD_write(1,0,row1);
- LCD_write(2,0,row2);
- LCD_write(3,0,Press_Change_Message);
-
- g_free (row0);
- g_free (row1);
- g_free (row2);
-
- return;
-}
-
-
-
+#include "i2c.h" +#include "lcd.h" +#include <glib.h> +#include <string.h> +#include <stdlib.h> + +#define LCD_ENABLE 0x03 /* the 4x40 LCDs have two enable lines - 0x03 enables both at the same time */ +#define LCD_DATA_RAM 128 /* display RAM, in the LCD ICs */ +#define LCD_CG_RAM 64 /* custom character RAM, in the LCD ICs */ + +#define LCD_chars_total 160 +#define LCD_cols 40 +#define LCD_rows 4 /* 4x40 LCD */ + +char LCD_Data[LCD_rows][LCD_cols]; /* shadow copy of LCD display in local RAM, to minimize slow I2C writes */ + +/*** EndHeader */ + + +static void break_up_string (char *in_string, int N, char **str1, char **str2, char **str3) +{ + +#define SUBSTRING_CNT 3 + + int input_length; + int j, k, copypos; + int n; + + char *copy_input; + char *p; + + j=k=copypos=0; + input_length=strlen(in_string); + copy_input = g_strdup(in_string); + + for (j=0; j<SUBSTRING_CNT; j++) { + + gchar *interm_str = g_strnfill (N, 0); + + for (k=0; k<N; k++) { + copypos++; // next symbol + if (copypos>input_length) { + break; + } + if ((*(copy_input+k)==' ')&&(copypos<input_length)) { // space found + //find next space + p=strchr(copy_input+k+1,' '); + if (p!=NULL) { + // next space is beyond N char limit for one line + if((p-copy_input)/sizeof(char)>=N) { + break; + } + } else { + // No more spaces. Does the last chunk of text fit? + if (strlen(copy_input+k+1)>N-k) { + break; + } + } + } + // valid character, copy to output string + *(interm_str+k)=*(copy_input+k); + + } + // remove processed part from the input + if (copypos<=input_length) { + strcpy(copy_input, in_string+copypos); + } + n = strlen(interm_str); + for ((k=n-1); (k=0); k--) { //trim space + if (*(interm_str+k)==' ') { + *(interm_str+k)=0; + } else { + break; + } + } + switch (j) { + case 0: + *str1 = g_strdup(interm_str); + break; + case 1: + *str2 = g_strdup(interm_str); + break; + case 2: + *str3 = g_strdup(interm_str); + break; + } + g_free(interm_str); + + } + + g_free(copy_input); +} + + + + +void LCD_clear() +{ + int i; + int j; + + I2C_Write(PCF8574A+LCD_Port, 0x00 | LCD_ENABLE); + I2C_Write(PCF8574A+LCD_Port, 0x00); + I2C_Write(PCF8574A+LCD_Port, 0x10 | LCD_ENABLE); + I2C_Write(PCF8574A+LCD_Port, 0x10); + + /* wait 1.64ms */ + g_usleep(1640); + + for (i=0; i<4; ++i) + for (j=0; j<40; ++j) { + LCD_Data[i][j]=0; + } + + return; +} + + +static void LCD_RAM_write(int RAM_start,int row, int col, char *LCD_string) +{ + /* rows: 0-3, cols: 0-39 */ + +#define data_level 0x04 + + int i; + int cur_row, cur_col; + int String_length; + char char_out, enable_one_lcd; + int ram_location; + char last_op_a_write; + + if (!LCD_string) { + return; + } + + String_length=strlen(LCD_string); + enable_one_lcd=0x02; + + last_op_a_write=0; + cur_row=row; + cur_col=col; + + if (cur_row<2) { + enable_one_lcd=0x02; + } else { + enable_one_lcd=0x01; + } + + /* write out the string */ + for (i=0; i<String_length; ++i) { + if (cur_row<2) { + enable_one_lcd=0x02; + } else { + enable_one_lcd=0x01; + } + + if (LCD_string[i]!=LCD_Data[cur_row][cur_col]) { + if (!last_op_a_write) { + /* move to new position */ + ram_location = (cur_row & 1) * 64 + cur_col + RAM_start; + char_out=ram_location & 0xf0; + I2C_Write(PCF8574A+LCD_Port, char_out | enable_one_lcd); + I2C_Write(PCF8574A+LCD_Port, char_out); + char_out=ram_location << 4; + I2C_Write(PCF8574A+LCD_Port, char_out | enable_one_lcd); + I2C_Write(PCF8574A+LCD_Port, char_out); + } + LCD_Data[cur_row][cur_col]=LCD_string[i]; + char_out=LCD_string[i] & 0xf0; + I2C_Write(PCF8574A+LCD_Port, char_out | enable_one_lcd | data_level); + I2C_Write(PCF8574A+LCD_Port, char_out | data_level); + char_out=LCD_string[i] << 4; + I2C_Write(PCF8574A+LCD_Port, char_out | enable_one_lcd | data_level); + I2C_Write(PCF8574A+LCD_Port, char_out | data_level); + last_op_a_write=1; + } else { + last_op_a_write=0; + } + + ++cur_col; + if (cur_col==40) { + cur_col=0; + ++cur_row; + } + } + return; +} + + +void LCD_write(int row, int col, char *LCD_string) +{ + LCD_RAM_write(LCD_DATA_RAM, row, col, LCD_string); + return; +} + + +static void LCD_make_custom_chars() +{ + /* define custom LCD characters 2 and 3 (up arrow and down arrow).*/ + /* The up arrow is stored in one LCD controller (for rows 0 and 1) */ + /* The down arrow is stored in the other LCD controller (for rows 2 and 3) */ + LCD_RAM_write(LCD_CG_RAM,0,16,"\x4"); + LCD_RAM_write(LCD_CG_RAM,0,17,"\xe"); + LCD_RAM_write(LCD_CG_RAM,0,18,"\x15"); + LCD_RAM_write(LCD_CG_RAM,0,19,"\x4"); + LCD_RAM_write(LCD_CG_RAM,0,20,"\x4"); + LCD_RAM_write(LCD_CG_RAM,0,21,"\x4"); + LCD_RAM_write(LCD_CG_RAM,0,22,"\x4"); + LCD_RAM_write(LCD_CG_RAM,0,23,"\x4"); + LCD_RAM_write(LCD_CG_RAM,2,24,"\x4"); + LCD_RAM_write(LCD_CG_RAM,2,25,"\x4"); + LCD_RAM_write(LCD_CG_RAM,2,26,"\x4"); + LCD_RAM_write(LCD_CG_RAM,2,27,"\x4"); + LCD_RAM_write(LCD_CG_RAM,2,28,"\x4"); + LCD_RAM_write(LCD_CG_RAM,2,29,"\x15"); + LCD_RAM_write(LCD_CG_RAM,2,30,"\xe"); + LCD_RAM_write(LCD_CG_RAM,2,31,"\x4"); +// prove that it works - debug only +// LCD_RAM_write(LCD_DATA_RAM,0,39,"\x2"); +// LCD_RAM_write(LCD_DATA_RAM,3,39,"\x3"); + + return; +} + + +void LCD_initialize(void) +{ + /* Wait 15ms */ + g_usleep(15000); + + I2C_Write(PCF8574A+LCD_Port, 0x30 | LCD_ENABLE); + I2C_Write(PCF8574A+LCD_Port, 0x30); + + /* wait 4.1ms */ + g_usleep(4100); + + I2C_Write(PCF8574A+LCD_Port, 0x30 | LCD_ENABLE); + I2C_Write(PCF8574A+LCD_Port, 0x30); + + /* wait 100us */ + g_usleep(100); + + I2C_Write(PCF8574A+LCD_Port, 0x30 | LCD_ENABLE); + I2C_Write(PCF8574A+LCD_Port, 0x30); + + /* wait 4.1ms */ + g_usleep(4100); + + I2C_Write(PCF8574A+LCD_Port, 0x20 | LCD_ENABLE); + I2C_Write(PCF8574A+LCD_Port, 0x20); + + /*wait 40us */ + g_usleep(40); + + I2C_Write(PCF8574A+LCD_Port, 0x20 | LCD_ENABLE); + I2C_Write(PCF8574A+LCD_Port, 0x20); + I2C_Write(PCF8574A+LCD_Port, 0x80 | LCD_ENABLE); + I2C_Write(PCF8574A+LCD_Port, 0x80); + + /* wait 40us */ + g_usleep(40); + + LCD_clear(); + + I2C_Write(PCF8574A+LCD_Port, 0x00 | LCD_ENABLE); + I2C_Write(PCF8574A+LCD_Port, 0x00); + I2C_Write(PCF8574A+LCD_Port, 0x60 | LCD_ENABLE); + I2C_Write(PCF8574A+LCD_Port, 0x60); + + /* wait 40us */ + g_usleep(40); + + I2C_Write(PCF8574A+LCD_Port, 0x00 | LCD_ENABLE); + I2C_Write(PCF8574A+LCD_Port, 0x00); + I2C_Write(PCF8574A+LCD_Port, 0xc0 | LCD_ENABLE); + I2C_Write(PCF8574A+LCD_Port, 0xc0); + + LCD_make_custom_chars(); + + return; +} + + +void LCD_display_error_message(char *response) +{ + char *row0 = NULL; + char *row1 = NULL; + char *row2 = NULL; + +// Error_Screen=1; //FIXME + + break_up_string (response, LCD_cols, &row0, &row1, &row2); + + LCD_clear(); + LCD_write(0,0,row0); + LCD_write(1,0,row1); + LCD_write(2,0,row2); + LCD_write(3,0,Press_Change_Message); + + g_free (row0); + g_free (row1); + g_free (row2); + + return; +} + + + @@ -1,7 +1,7 @@ -#define Press_Change_Message "Push CHANGE to continue."
-
-
-void LCD_display_error_message(char *response);
-void LCD_clear();
-void LCD_write(int row, int col, char *LCD_string);
-void LCD_initialize(void);
+#define Press_Change_Message "Push CHANGE to continue." + + +void LCD_display_error_message(char *response); +void LCD_clear(); +void LCD_write(int row, int col, char *LCD_string); +void LCD_initialize(void); @@ -1,1011 +1,1011 @@ -/* START LIBRARY DESCRIPTION *********************************************
-PARSER.LIB
- Copyright (c) 1997, Avtech Electrosystems Ltd.
-
-DESCRIPTION:
- Parser functions.
-
-SUPPORT LIB'S:
-END DESCRIPTION **********************************************************/
-
-
-#include "parser.h"
-#include <glib/gprintf.h>
-
-//STATICS
-static int query_int (gchar** response, int n);
-static int query_min_max_float (gchar** response, char *parameter, float min_val, float max_val);
-static int query_float (gchar** response, float value);
-static int process_float_param (char *parameter, float *value, float min_val, float max_val, int zero_mode);
-static int check_channel_ok (int channel, int enabled_channels, char chankey);
-static int Parser_id_word(char *id_me, int *channel, int *with_id_code);
-static int Parser_find_commands(int commands[], int command_depth);
-static int Parser_get_unit(char **parameter, char **units);
-static int Parser_channel (int *channel,int with_id_code,int routine_num);
-static int Go_freq_32_33(gchar** response, int channel, char *parameter,char *units,int command_type);
-static int Handle_Units(float *mult,char *units, char *base);
-static int Is_Min_Command(char *text);
-static int Is_Max_Command(char *text);
-static int Go_syst_err_11(gchar** response, int channel, char *parameter,char *units,int command_type);
-static int Go_syst_errcnt66(gchar** response, int channel, char *parameter,char *units,int command_type);
-
-static int Parser_id_word(char *id_me, int *channel, int *with_id_code)
-{
- int id_code;
- int set_new_channel;
-
- set_new_channel=0;
-
- /* detect channel suffixes in the range of 0-99 */
- if (isdigit((int) id_me[strlen(id_me)-1])) {
- set_new_channel=1;
- *channel=atoi(id_me+strlen(id_me)-1);
- if (isdigit((int) id_me[strlen(id_me)-2])) {
- *channel=atoi(id_me+strlen(id_me)-2);
- id_me[strlen(id_me)-2]=0;
- } else {
- id_me[strlen(id_me)-1]=0;
- }
- }
-
-
- if (!strcmp(id_me,"*cls") ) {
- id_code = 1;
- } else if (!strcmp(id_me,"*ese") ) {
- id_code = 2;
- } else if (!strcmp(id_me,"*esr") ) {
- id_code = 4;
- } else if (!strcmp(id_me,"*idn") ) {
- id_code = 5;
- } else if (!strcmp(id_me,"*opc") ) {
- id_code = 6;
- } else if (!strcmp(id_me,"*rst") ) {
- id_code = 8;
- } else if (!strcmp(id_me,"*sre") ) {
- id_code = 9;
- } else if (!strcmp(id_me,"*stb") ) {
- id_code = 10;
- } else if (!strcmp(id_me,"*tst") ) {
- id_code = 11;
- } else if (!strcmp(id_me,"*wai") ) {
- id_code = 12;
- } else if (!strcmp(id_me,"system") || !strcmp(id_me,"syst")) {
- id_code = 13;
- } else if (!strcmp(id_me,"error") || !strcmp(id_me,"err")) {
- id_code = 14;
- } else if (!strcmp(id_me,"version") || !strcmp(id_me,"vers")) {
- id_code = 15;
- } else if (!strcmp(id_me,"status") || !strcmp(id_me,"stat") || !strcmp(id_me,"state")) {
- id_code = 16;
- } else if (!strcmp(id_me,"operation") || !strcmp(id_me,"oper")) {
- id_code = 17;
- } else if (!strcmp(id_me,"event") || !strcmp(id_me,"even")) {
- id_code = 18;
- } else if (!strcmp(id_me,"condition") || !strcmp(id_me,"cond")) {
- id_code = 19;
- } else if (!strcmp(id_me,"enable") || !strcmp(id_me,"enab")) {
- id_code = 20;
- } else if (!strcmp(id_me,"questionable") || !strcmp(id_me,"ques")) {
- id_code = 21;
- } else if (!strcmp(id_me,"preset") || !strcmp(id_me,"pres")) {
- id_code = 22;
- } else if (!strcmp(id_me,"diagnostic") || !strcmp(id_me,"diag")) {
- id_code = 23;
- } else if (!strcmp(id_me,"output") || !strcmp(id_me,"outp")) {
- id_code = 24;
- } else if (!strcmp(id_me,"impedance") || !strcmp(id_me,"imp")) {
- id_code = 25;
- } else if (!strcmp(id_me,"protection") || !strcmp(id_me,"prot")) {
- id_code = 26;
- } else if (!strcmp(id_me,"tripped") || !strcmp(id_me,"trip")) {
- id_code = 27;
- } else if (!strcmp(id_me,"source") || !strcmp(id_me,"sour")) {
- id_code = 28;
- } else if (!strcmp(id_me,"current") || !strcmp(id_me,"curr")) {
- id_code = 29;
- } else if (!strcmp(id_me,"level") || !strcmp(id_me,"lev")) {
- id_code = 30;
- } else if (!strcmp(id_me,"immediate") || !strcmp(id_me,"imm")) {
- id_code = 31;
- } else if (!strcmp(id_me,"amplitude") || !strcmp(id_me,"ampl")) {
- id_code = 32;
- } else if (!strcmp(id_me,"offset") || !strcmp(id_me,"offs")) {
- id_code = 33;
- } else if (!strcmp(id_me,"high") ) {
- id_code = 34;
- } else if (!strcmp(id_me,"low") ) {
- id_code = 35;
- } else if (!strcmp(id_me,"voltage") || !strcmp(id_me,"volt")) {
- id_code = 36;
- } else if (!strcmp(id_me,"frequency") || !strcmp(id_me,"freq")) {
- id_code = 37;
- } else if (!strcmp(id_me,"function") || !strcmp(id_me,"func")) {
- id_code = 38;
- } else if (!strcmp(id_me,"shape") || !strcmp(id_me,"shap")) {
- id_code = 39;
- } else if (!strcmp(id_me,"pulse") || !strcmp(id_me,"puls")) {
- id_code = 40;
- } else if (!strcmp(id_me,"period") || !strcmp(id_me,"per")) {
- id_code = 41;
- } else if (!strcmp(id_me,"width") || !strcmp(id_me,"widt")) {
- id_code = 42;
- } else if (!strcmp(id_me,"dcycle") || !strcmp(id_me,"dcyc")) {
- id_code = 43;
- } else if (!strcmp(id_me,"hold") ) {
- id_code = 44;
- } else if (!strcmp(id_me,"delay") || !strcmp(id_me,"del")) {
- id_code = 45;
- } else if (!strcmp(id_me,"double") || !strcmp(id_me,"doub")) {
- id_code = 46;
- } else if (!strcmp(id_me,"polarity") || !strcmp(id_me,"pol")) {
- id_code = 47;
- } else if (!strcmp(id_me,"beeper") || !strcmp(id_me,"beep")) {
- id_code = 48;
- } else if (!strcmp(id_me,"cw") ) {
- id_code = 49;
- } else if (!strcmp(id_me,"fixed") || !strcmp(id_me,"fix")) {
- id_code = 50;
- } else if (!strcmp(id_me,"abort") || !strcmp(id_me,"abor")) {
- id_code = 51;
- } else if (!strcmp(id_me,"initiate") || !strcmp(id_me,"init")) {
- id_code = 52;
- } else if (!strcmp(id_me,"continuous")) {
- id_code = 53;
- } else if (!strcmp(id_me,"trigger") || !strcmp(id_me,"trig")) {
- id_code = 54;
- } else if (!strcmp(id_me,"integer") || !strcmp(id_me,"int")) {
- id_code = 55;
- } else if (!strcmp(id_me,"float") ) {
- id_code = 56;
- } else if (!strcmp(id_me,"eprom") ) {
- id_code = 57;
- } else if (!strcmp(id_me,"string") ) {
- id_code = 58;
- } else if (!strcmp(id_me,"bit") ) {
- id_code = 59;
- } else if (!strcmp(id_me,"set") ) {
- id_code = 60;
- } else if (!strcmp(id_me,"clear") ) {
- id_code = 61;
- } else if (!strcmp(id_me,"shiftreg") ) {
- id_code = 62;
- } else if (!strcmp(id_me,"*rcl") ) {
- id_code = 63;
- } else if (!strcmp(id_me,"*sav") ) {
- id_code = 64;
- } else if (!strcmp(id_me,"gate") ) {
- id_code = 65;
- } else if (!strcmp(id_me,"local") || !strcmp(id_me,"logout") || !strcmp(id_me,"exit") || !strcmp(id_me,"quit") ) {
- id_code = 66;
- } else if (!strcmp(id_me,"test") ) {
- id_code = 67;
- } else if (!strcmp(id_me,"communicate") || !strcmp(id_me,"comm")) {
- id_code = 68;
- } else if (!strcmp(id_me,"address") || !strcmp(id_me,"addr")) {
- id_code = 69;
- } else if (!strcmp(id_me,"gpib") ) {
- id_code = 70;
- } else if (!strcmp(id_me,"serial") || !strcmp(id_me,"ser")) {
- id_code = 71;
- } else if (!strcmp(id_me,"receive") || !strcmp(id_me,"rec")) {
- id_code = 72;
- } else if (!strcmp(id_me,"baud") ) {
- id_code = 73;
- } else if (!strcmp(id_me,"parity") || !strcmp(id_me,"par")) {
- id_code = 74;
- } else if (!strcmp(id_me,"type") ) {
- id_code = 75;
- } else if (!strcmp(id_me,"bits") ) {
- id_code = 76;
- } else if (!strcmp(id_me,"sbits") || !strcmp(id_me,"sbit")) {
- id_code = 77;
- } else if (!strcmp(id_me,"echo") ) {
- id_code = 78;
- } else if (!strcmp(id_me,"rts") ) {
- id_code = 79;
- } else if (!strcmp(id_me,"control") || !strcmp(id_me,"cont")) {
- id_code = 80;
- } else if (!strcmp(id_me,"next") ) {
- id_code = 81;
- } else if (!strcmp(id_me,"count") || !strcmp(id_me,"coun")) {
- id_code = 82;
- } else if (!strcmp(id_me,"display") || !strcmp(id_me,"disp")) {
- id_code = 83;
- } else if (!strcmp(id_me,"brightness") || !strcmp(id_me,"brig")) {
- id_code = 84;
- } else if (!strcmp(id_me,"load") ) {
- id_code = 85;
- } else if (!strcmp(id_me,"measure") || !strcmp(id_me,"meas")) {
- id_code = 86;
- } else if (!strcmp(id_me,"char") ) {
- id_code = 87;
- } else if (!strcmp(id_me,"calibration") || !strcmp(id_me,"cal")) {
- id_code = 88;
- } else if (!strcmp(id_me,"monitor") || !strcmp(id_me,"mon")) {
- id_code = 89;
- } else if (!strcmp(id_me,"step") ) {
- id_code = 90;
- } else if (!strcmp(id_me,"route") || !strcmp(id_me,"rout")) {
- id_code = 91;
- } else if (!strcmp(id_me,"close") || !strcmp(id_me,"clos")) {
- id_code = 92;
- } else if (!strcmp(id_me,"point") ) {
- id_code = 93;
- } else if (!strcmp(id_me,"shift") ) {
- id_code = 94;
- } else if (!strcmp(id_me,"scale") ) {
- id_code = 95;
- } else if (!strcmp(id_me,"null") ) {
- id_code = 96;
- } else if (!strcmp(id_me,"size") ) {
- id_code = 97;
- } else if (!strcmp(id_me,"separation") || !strcmp(id_me,"sep")) {
- id_code = 98;
- } else if (!strcmp(id_me,"network") || !strcmp(id_me,"net")) {
- id_code = 99;
- } else if (!strcmp(id_me,"password") || !strcmp(id_me,"pass")) {
- id_code = 100;
- } else if (!strcmp(id_me,"new") ) {
- id_code = 101;
- } else if (!strcmp(id_me,"suspend") ) {
- id_code = 102;
- } else if (!strcmp(id_me,"transition") || !strcmp(id_me,"tran")) {
- id_code = 103;
- } else if (!strcmp(id_me,"leading") || !strcmp(id_me,"lead")) {
- id_code = 104;
- } else if (!strcmp(id_me,"limit") || !strcmp(id_me,"lim")) {
- id_code = 105;
- } else if (!strcmp(id_me,"slew") ) {
- id_code = 106;
- } else if (!strcmp(id_me,"all") ) {
- id_code = 107;
- }
-
- else {
- id_code = 9999;
- }
-
- if (set_new_channel) {
- *with_id_code=id_code;
- }
-
- return id_code;
-
-}
-
-static int Parser_find_commands(int commands[], int command_depth)
-{
-#define optional 16384 /* set bit high if optional */
-#define opt_mask 16383 /* default bit mask */
-#define max_tokens_in_sentence 7
-#define max_no_of_sentences 110
-
- /* Valid command -sequences-. The -individual- commands are defined in id_word. */
-
- static const int sentences[max_no_of_sentences][max_tokens_in_sentence] = {
- {0}, /* null - error */
- {1}, /* cls - sentence 1 */
- {2}, /* ese - sentence 2 */
- {4}, /* esr - sentence 3 */
- {5}, /* idn - sentence 4 */
- {6}, /* opc - sentence 5 */
- {8}, /* rst - sentence 6 */
- {9}, /* sre - sentence 7 */
- {10}, /* stb - sentence 8 */
- {11}, /* tst - sentence 9 */
- {12}, /* wai - sentence 10 */
- {13,14,81|optional}, /* syst:err:next - 11 */
- {13,15}, /* syst:vers - 12 */
- {16,17,18|optional}, /* stat:oper:event - 13 */
- {16,17,19}, /* stat:oper:cond - 14 */
- {16,17,20}, /* stat:oper:enable - 15 */
- {16,21,18|optional}, /* stat:ques:event - 16 */
- {16,21,19}, /* stat:ques:cond - 17 */
- {16,21,20}, /* stat:ques:enable - 18 */
- {16,22}, /* stat:preset - 19 */
- {24,25}, /* output:impedance - 20 */
- {24,26,27}, /* output:prot:tripped - 21 */
- {28|optional,29,30|optional,31|optional,32|optional}, /* sour:curr:lev:imm:ampl - 22 */
- {28|optional,29,30|optional,31|optional,33}, /* sour:curr:lev:imm:offset - 23 - not used */
- {28|optional,29,30|optional,31|optional,34}, /* sour:curr:lev:imm:high - 24 - not used */
- {28|optional,29,30|optional,31|optional,35}, /* sour:curr:lev:imm:low - 25 */
- {28|optional,36,30|optional,31|optional,32|optional}, /* sour:volt:lev:imm:ampl - 26 */
- {28|optional,36,30|optional,31|optional,33}, /* sour:volt:lev:imm:offset - 27 - not used */
- {28|optional,36,30|optional,31|optional,34}, /* sour:volt:lev:imm:high - 28 - not used */
- {28|optional,36,30|optional,31|optional,35}, /* sour:volt:lev:imm:low - 29 */
- {28|optional,29,26,27}, /* sour:curr:prot:tripped? - 30 */
- {28|optional,36,26,27}, /* sour:volt:prot:tripped? - 31 */
- {28|optional,37,49|optional}, /* sour:freq:cw - 32 */
- {28|optional,37,50|optional}, /* sour:freq:fixed - 33 */
- {28|optional,38,39|optional}, /* sour:func:shape - 34 */
- {28|optional,40,41}, /* sour:puls:per - 35 */
- {28|optional,40,42}, /* sour:puls:width - 36 */
- {28|optional,40,43}, /* sour:puls:dcyc - 37 */
- {28|optional,40,44}, /* sour:puls:hold - 38 */
- {28|optional,40,45}, /* sour:puls:delay - 39 */
- {28|optional,40,46,16|optional}, /* sour:puls:doub:state - 40 */
- {28|optional,40,46,45}, /* sour:puls:doub:delay - 41 */
- {28|optional,40,47}, /* sour:puls:pol - 42 */
- {13,48,31|optional}, /* syst:beep:imm - 43 - not used */
- {52,31|optional,53}, /* init:imm:cont - 44 - not used */
- {51}, /* abort - 45 - not used */
- {54,31|optional,28}, /* trig:imm:sour - 46 */
- {23,57,58}, /* diag:eprom:string - 47 */
- {23,57,55}, /* diag:eprom:int - 48 */
- {23,57,59,60}, /* diag:eprom:bit:set - 49 - not used */
- {23,57,59,61}, /* diag:eprom:bit:clear - 50 - not used */
- {23,57,56}, /* diag:eprom:float - 51 */
- {23,62}, /* diag:shiftreg - 52 */
- {63}, /* *rcl - 53 */
- {64}, /* *sav - 54 */
- {24,16|optional}, /* output:state - 55 */
- {28|optional,40,65,75}, /* sour:puls:gate:type - 56 */
- {66}, /* local (RS232 mode only) - 57 */
- {23,67,45}, /* diag:test:delay - 58 */
- {13,68,70,69}, /* syst:comm:gpib:addr - 59 */
- {13,68,71,72|optional,73}, /* syst:comm:ser:rec:baud - 60 */
- {13,68,71,72|optional,74,75|optional}, /* syst:comm:ser:rec:parity - 61 */
- {13,68,71,72|optional,76}, /* syst:comm:ser:rec:bits - 62 */
- {13,68,71,72|optional,77}, /* syst:comm:ser:rec:sbits - 63 */
- {13,68,71,80,79}, /* syst:comm:ser:control:rts - 64 */
- {13,68,71,72|optional,78}, /* syst:comm:ser:rec:echo - 65 */
- {13,14,82}, /* syst:err:count - 66 */
- {28|optional,40,65,30}, /* sour:puls:gate:level - 67 */
- {24,85}, /* output:load - 68 */
- {86,32}, /* meas:ampl? - 69 */
- {23,57,87}, /* diag:eprom:char - 70 */
- {23,88}, /* diag:calib - 71 */
- {23,32,88,95|optional}, /* diag:ampl:calib:scale - 72 */
- {23,89,88,95|optional}, /* diag:mon:calib:scale - 73 */
- {23,89,90}, /* diag:mon:step - 74 */
- {24,75}, /* output:type - 75 */
- {23,33,88,95|optional}, /* diag:offset:calib:scale - 76 */
- {23,40,42,88,94}, /* diag:pulse:width:calib:shift - 77 */
- {91,92}, /* route:close - 78 */
- {23,40,42,88,93}, /* diag:pulse:width:calib:point - 79 */
- {23,40,45,88,93}, /* diag:pulse:delay:calib:point - 80 */
- {23,40,41,88,93}, /* diag:pulse:period:calib:point - 81 */
- {23,40,45,88,94}, /* diag:pulse:delay:calib:shift - 82 */
- {23,32,88,93}, /* diag:ampl:calib:point - 83 */
- {23,33,88,93}, /* diag:offset:calib:point - 84 */
- {23,33,96,93}, /* diag:offset:null:point - 85 */
- {23,57,97}, /* diag:eprom:size - 86 */
- {83,84}, /* display:brightness - 87 */
- {28|optional,40,82}, /* sour:puls:count - 88 */
- {28|optional,40,98}, /* sour:puls:separation - 89 */
- {23,40,98,88,93}, /* diag:pulse:separation:calib:point - 90 */
- {13,68,99}, /* system:comm:network - 91 */
- {13,100,101}, /* system:password:new - 92 */
- {23,57,102}, /* diag:eprom:suspend - 93 */
- {28|optional,40,103,104|optional}, /* sour:puls:transition:leading - 94 */
- {23,40,103,88,93}, /* diag:pulse:transition:calib:point - 95 */
- {28|optional,29,105,32|optional}, /* sour:curr:limit:ampl - 96 */
- {23,24,85,88,93}, /* diag:output:load:calib:point - 97 */
- {28|optional,29,106}, /* sour:curr:slew - 98 */
- {23,106,88,93}, /* diag:slew:calib:point - 99 */
- {88,107|optional}, /* calibration:all - 100 */
- {88,37} /* calibration:frequency - 101 */
-
- };
-
-
- int token_num; /* which token in the command[] list is being considered */
- int sentence_num; /* which sentence is being considered as a match */
- int sentence_found; /* matching sentence found yet? */
- int sent_pos; /* position in current sentence */
- int invalid_match; /* flag if definitely the wrong match */
- int local_match_pos; /* position (or pos+1, depends) of most-recently-matched token in sentence */
- int local_match; /* match for current token found yet? */
- int prev_match; /* were there previous local matches? */
- int i; /* a counter */
-
- sentence_num = 1;
- sent_pos = 0;
-
- /* check each "sentence" (corresponding to a different routine or function)
- until a match is found, or until their are no possible sentences left */
- for (sentence_found = 0; (!sentence_found && sentence_num < max_no_of_sentences); ++sentence_num) {
- local_match_pos=0;
- invalid_match=0;
- prev_match=0;
- /* start with the first input token, until all have been matched, or one
- is unmatchable */
- for (token_num = 0; (token_num < command_depth) && !invalid_match; ++token_num) {
- /* start after most recent matching token */
- sent_pos=local_match_pos;
-
- /* compare current token to the sentence components until a matching component
- is found, or until there are none left */
- for (local_match=0; (!local_match) && (sent_pos<max_tokens_in_sentence); ++sent_pos) {
-
- /* compare here */
- if (commands[token_num]==((sentences[sentence_num][sent_pos]) & opt_mask)) {
- /* flag a local token match (not a whole sentence match) */
- local_match=1;
- }
- }
- if (local_match) {
- /* if any of the components in the sentence were skipped between the last two
- matches, make sure that they were optional ones */
- if (!prev_match) {
- local_match_pos=-1;
- }
- /* if there was no local match previously, then the initial value
- of local_match_pos is misleading - there was no match at 0. */
- for (i=(local_match_pos+1); i<(sent_pos-1); ++i) {
- /* if they weren't optional, the match is not valid */
- if (!(sentences[sentence_num][i] & optional)) {
- invalid_match=1;
- }
- }
- /* counteract the last "++i" due to the for loop */
- local_match_pos = sent_pos - 1;
- if (local_match && !invalid_match) {
- prev_match=1;
- }
- }
-
- /* if no match for this one token existed in this sentence, mark this sentence as invalid */
- if (!local_match) {
- invalid_match = 1;
- }
- }
- /* if no invalid token match was found for any of the tokens in this sentence,
- then it's an overall sentence match! */
- if (!invalid_match) {
- sentence_found=1;
- }
- }
- --sentence_num;
-
- if (!sentence_found) {
- sentence_num = 0;
- }
- /* 0 is the no-match value */
-
- return sentence_num;
-}
-
-
-static int Parser_get_unit(char **parameter, char **units)
-{
- /* this function takes a parameter like "1e+6 ms" and breaks it into parameter="1e+6" and
- units="ms" */
-
- if (*parameter == NULL) {
- *parameter = g_strdup ("");
- }
-
- g_assert (*units == NULL);
-
- gchar *end_ptr;
- g_strtod (*parameter, &end_ptr);
-
- if (end_ptr == *parameter) {
- *units = g_strdup ("");
- } else {
- *units = g_strdup (end_ptr);
- end_ptr[0] = 0; // truncates parameter
- }
-
- g_strstrip (*units);
- g_strstrip (*parameter);
-
- int units_present = (*units[0] != 0);
- return units_present;
-}
-
-void Parser_main (char *raw_in, int interactive_terminal, void(*cbfunc)(gpointer, gchar *), gpointer user_data)
-{
- int in_pos; /* this identifies the single character of in being processed */
- int command_depth; /* how many command words have been parsed */
- int old_command_depth; /* save this if in case of a compound message */
- char current_command[max_input_word_length]; /* current command word being processed */
- int current_command_length; /* length of current command so far */
- int commands[max_commands_in_input]; /* list of identified command tokens */
- int old_commands[max_commands_in_input]; /* list of identified command tokens from */
- /* last non-common, non-colon-started command*/
- int space_found; /* if true, a space was found. parameter may follow */
- int parameter_found; /* if true, there is a parameter at the end of the command string */
- int semicolon_found; /* to break up lines */
- int units_found; /* text found after parameter must be units */
- int i; /* counter */
- int routine_num; /* routine to execute, based on command */
- int dont_use_this_header; /* the old head is saved in case of compound message, unless this is set */
- int compound_message; /* this indicates that at least one semicolon has been found, so */
- /* the message is a compound one */
-
-
- int is_query;
- int command_type; /* combination of is_query, parameter_found, and units_found */
-
- int channel;
- int with_id_code;
-
- g_strstrip (raw_in);
-
- // add white space to the end of the input string - FIXME?
- gchar *in = g_strdup_printf ("%s ", raw_in);
-
- in_pos = 0; /* start at the beginning of the input string */
- semicolon_found = 0;
- compound_message = 0;
- command_depth=0;
- old_command_depth=0;
- dont_use_this_header=NO;
-
- while (isspace(in[in_pos]) || in[in_pos]==':' || in[in_pos]==';') {
- /* ignore leading spaces */
- ++in_pos;
- }
-
-
- /* examine each letter in the string until EOS */
- while (in[in_pos] != 0) {
-
- gchar *units = NULL;
- gchar *response = NULL;
- gchar *error_response = NULL;
- gchar *parameter = NULL;
-
- channel=-1;
- with_id_code=0;
- space_found = 0;
- parameter_found = 0; /* no numeric parameters yet */
- units_found = 0;
- is_query = 0;
- current_command_length = 0;
-
- if (semicolon_found && !dont_use_this_header) {
- old_command_depth=command_depth-2;
- for (i=0; i<old_command_depth; ++i) {
- old_commands[i]=commands[i];
- }
- }
-
- command_depth=old_command_depth;
- for (i=0; i<command_depth; ++i) {
- commands[i]=old_commands[i];
- }
-
- semicolon_found=0;
- dont_use_this_header=NO;
-
- /* break it up if semicolons are present */
- while (!semicolon_found && in[in_pos] != 0) {
-
- in[in_pos]=tolower(in[in_pos]);
- /* everything to lowercase */
-
- /* words are separated by white space or colons or semicolons */
- if ( isspace(in[in_pos]) || in[in_pos] == ':' || in[in_pos] == ';')
-
- {
-
- if (in[in_pos] == ';') {
- ++semicolon_found;
- }
- ++compound_message;
-
- /* if it is a separator, ignore it if it is duplicated */
- if ( !isspace(in[in_pos-1]) && (in[in_pos-1] != ':') && (in[in_pos-1] != ';')) {
- /* valid separator, so terminate current command word string */
- current_command[current_command_length] = '\0';
-
- if (space_found) {
- /* Just end things if it is a semicolon */
- if (in[in_pos]!=';') {
- current_command[current_command_length] = in[in_pos];
- ++current_command_length;
- }
-
- current_command[current_command_length] = '\0';
- ++parameter_found;
- parameter = g_strdup (current_command);
- } else if (!space_found) {
- /* just a regular command word */
-
- /* terminate the current command string */
- current_command_length = 0; /* make room for a new command string */
- commands[command_depth]=Parser_id_word(current_command,&channel,&with_id_code);
-
- if ( commands[command_depth]<13
- || commands[command_depth]==63
- || commands[command_depth]==64) {
- dont_use_this_header=YES;
- commands[0]=commands[command_depth];
- command_depth=0;
- }
-
- ++command_depth; /* indicate that a new command word is ready */
-
- /* indicate if the separator was a space - next bit parameter then */
- if (in[in_pos]==' ') {
- ++space_found;
- }
- }
- } /* non-repeated separator */
- else if (compound_message && in[in_pos-1]==';' && in[in_pos]==':') {
- dont_use_this_header=YES;
- command_depth=0;
- }
-
- } /* a separator */
- else if (in[in_pos]!='?') {
- /* if not white space or separator, add character to current command word */
- current_command[current_command_length] = in[in_pos];
- ++current_command_length;
- } /* not a separator */
- else {
- ++is_query;
- /* question mark found */
- }
-
-
- ++in_pos; /* move pointer to next letter */
-
- } /* not a semi-colon */
-
- commands[command_depth]=0;
- ++command_depth;
- /* add end of tokens marker (0) */
-
- int error_num=OK;
-
- units_found = Parser_get_unit(¶meter,&units);
-
- if (!error_num) {
- command_type=(is_query<<2) | (parameter_found?2:0) | units_found;
-
- if (commands[0]!=0) {
- routine_num = Parser_find_commands(commands,command_depth);
-
- /* check for valid channel number, based on position in command */
- if ( (error_num=Parser_channel(&channel,with_id_code,routine_num)) )
- /* not a valid command due to improper channel suffix */
- {
- routine_num=9999;
- }
- } else {
- routine_num=9999;
- /* ignore empty commands lists, generated by a white space string */
- }
-
- switch (routine_num) {
- case 0:
- response = g_strdup_printf("routine_num: %d, channel: %d, parameter: %s, units: %s, command type: %d",routine_num,channel,parameter,units,command_type);
- error_num=Unrecognized;
- break;
- case 11:
- error_num=Go_syst_err_11(&response,channel,parameter,units,command_type);
- break;
- case 32:
- case 33:
- error_num=Go_freq_32_33(&response,channel,parameter,units,command_type);
- break;
- case 66:
- error_num=Go_syst_errcnt66(&response,channel,parameter,units,command_type);
- break;
-
- case 9999:
- // was only whitespace, ignore
- break;
-
- default:
- /* valid but not implemented yet */
- response = g_strdup_printf("routine_num: %d, channel: %d, parameter: %s, units: %s, command type: %d",routine_num,channel,parameter,units,command_type);
- break;
-
- }
- }
-
- if (error_num) {
- queue_error_from_parser(&error_response, error_num);
- if (interactive_terminal) {
- (*cbfunc)(user_data, error_response);
- }
- } else {
- (*cbfunc)(user_data, response);
- }
-
- g_free (units);
- g_free (response);
- g_free (error_response);
- g_free (parameter);
-
- if (!is_query) {
- Main_update_shift_registers(); /* update values in pulse generator circuit */
- }
-
- } /* not EOS */
-
- /* update display if it wasn't a query, and if the control menu isn't on (this gives the user
- a chance to press "Go To Local" to override control */
-
- int Selected_Submenu=0, Submenu1_rem_loc=0, Type_Of_Menu=0, Submenu_On=0;
-
- if (!is_query && !(Selected_Submenu==Submenu1_rem_loc && Type_Of_Menu==Submenu_On)) {
- Menu_Update_Display();
- }
-
- /* re-run error_check to update min/max values based on actual settings, not proposed settings */
- Error_check(globals.ChannelState);
-
- // trigger a prompt
- if (interactive_terminal) {
- (*cbfunc)(user_data, "");
- }
-
- g_free (in);
-}
-
-
-static int Parser_channel (int *channel,int with_id_code,int routine_num)
-{
- /* return if no channel suffixes appeared */
- if (*channel==-1) {
- *channel=0;
- return OK;
- }
-
-
- /* compare to maximum number of channels allowed */
- if (*channel>1 && *channel>globals.Flash.channels && !globals.Flash.enable_avrq_extra_ampls) {
- return InvalidChannel;
- }
- if (*channel>5 && globals.Flash.enable_avrq_extra_ampls) {
- return InvalidChannel;
- }
-
-
- /* SCPI uses 1-N counting, change to 0 - (N-1) */
- if (*channel > 0) {
- --(*channel);
- } else {
- return InvalidChannel;
- }
-
- return OK;
-}
-
-
-static int Go_freq_32_33(gchar** response, int channel, char *parameter,char *units,int command_type)
-{
- // this is a typical parser function - there will be many more added later
-
- float new_freq;
- int status;
-
- if ( (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_frequency))) {
- return status;
- }
-
- new_freq=1.0;
-
- switch (command_type) {
- case command_param_units:
- if ( (status=Handle_Units(&new_freq,units,"hz")) ) {
- return status;
- }
- /* no break */
-
- case command_withparam:
- if ( (status = process_float_param (parameter, &new_freq, 1.0, 1.0e6, NORMAL_ZERO)) ) {
- return status;
- }
- return Set_frequency(0,0,0,channel,new_freq);
- break;
-
- case query_simple:
- return query_float(response, globals.ChannelState[channel].frequency);
- break;
-
- case query_param:
- return query_min_max_float (response, parameter, 1.0, 1.0e6);
- break;
-
- default:
- return SyntaxError;
- break;
- }
-}
-
-
-static int Handle_Units(float *mult,char *units, char *in_base)
-{
- int len_base, len_all, pos;
- char prefix[max_input_word_length];
- char base[max_input_word_length];
-
- strcpy (base, in_base);
-
- *mult=1.0;
- if (!strcmp(units,base)) {
- return OK;
- }
-
- // match base
- len_all = strlen (units);
- if (len_all == 0) {
- return OK;
- }
-
- len_base = strlen (base);
- pos = len_all - len_base;
-
- strcpy (prefix, units);
-
- if (!strcmp(base,"%") && (len_all >= 3) && !strcmp(prefix + len_all - 3,"pct")) {
- strcpy(base, "pct");
- prefix[len_all - 3] = 0;
- } else if (!strcmp(base,"pct") && !strcmp(prefix + len_all - 1,"%")) {
- strcpy(base, "%");
- prefix[len_all - 1] = 0;
- } else if (strcmp(prefix+pos,base)) {
- return UnknownUnits;
- } else {
- prefix[pos]=0;
- }
-
- if (strlen(prefix) == 0) {
- return OK;
- }
-
- // special exceptions
- if (!strcmp(prefix,"m") && !strcmp(base,"ohm")) {
- *mult=1.0e6;
- } else if (!strcmp(prefix,"m") && !strcmp(base,"hz")) {
- *mult=1.0e6;
- }
- // normal rules
- else if (!strcmp(prefix,"ex")) {
- *mult=1.0e18;
- } else if (!strcmp(prefix,"pe")) {
- *mult=1.0e15;
- } else if (!strcmp(prefix,"t")) {
- *mult=1.0e12;
- } else if (!strcmp(prefix,"g")) {
- *mult=1.0e9;
- } else if (!strcmp(prefix,"ma")) {
- *mult=1.0e6;
- } else if (!strcmp(prefix,"k")) {
- *mult=1.0e3;
- } else if (!strcmp(prefix,"m")) {
- *mult=1.0e-3;
- } else if (!strcmp(prefix,"u")) {
- *mult=1.0e-6;
- } else if (!strcmp(prefix,"n")) {
- *mult=1.0e-9;
- } else if (!strcmp(prefix,"p")) {
- *mult=1.0e-12;
- } else if (!strcmp(prefix,"f")) {
- *mult=1.0e-15;
- } else if (!strcmp(prefix,"a")) {
- *mult=1.0e-18;
- } else {
- return UnknownUnits;
- }
-
- return OK;
-}
-
-
-static int Is_Min_Command(gchar *text)
-{
- return (!strcmp(text,"min") || !strcmp(text,"minimum"));
-}
-
-
-static int Is_Max_Command(char *text)
-{
- return (!strcmp(text,"max") || !strcmp(text,"maximum"));
-}
-
-static int query_int (gchar** response, int n)
-{
- *response = g_strdup_printf ("%d", n);
- return OK;
-}
-
-static int query_min_max_float (gchar** response, char *parameter, float min_val, float max_val)
-{
- float report_val;
-
- if (Is_Min_Command(parameter)) {
- report_val=min_val;
- } else if (Is_Max_Command(parameter)) {
- report_val=max_val;
- } else {
- return SyntaxError;
- }
-
- Float_To_Text(remote_digits_after_decimal,report_val,response);
- return OK;
-}
-
-static int query_float (gchar** response, float value)
-{
- Float_To_Text(remote_digits_after_decimal,value,response);
- return OK;
-}
-
-static int process_float_param (char *parameter, float *value, float min_val, float max_val, int zero_mode)
-{
- int status;
- status = OK;
-
- if (String_is_it_numeric(parameter)) {
- *value *= atof(parameter);
-
- if (zero_mode == ALLOW_NEG_ZERO) {
- /* allow a value of "-0" */
- if (fabs(*value) < smallest_allowed_number)
- if (parameter[0] == '-') {
- *value = -0.1*smallest_allowed_number;
- }
- }
- }
-
- else if (!strcmp(parameter,"+") && (zero_mode == ALLOW_NEG_ZERO)) {
- *value = smallest_allowed_number;
- } else if (!strcmp(parameter,"-") && (zero_mode == ALLOW_NEG_ZERO)) {
- *value = -smallest_allowed_number;
- } else if (Is_Min_Command(parameter)) {
- *value = min_val;
- } else if (Is_Max_Command(parameter)) {
- *value = max_val;
- } else {
- status=SyntaxError;
- }
-
- return status;
-}
-
-static int check_channel_ok (int channel, int enabled_channels, char chankey)
-{
- /* how many channels overall */
- if (channel >= enabled_channels) {
- return InvalidChannel;
- }
-
- /* abandon if high channel selected by user but not enabled by firmware for that parameter*/
- if (channel && !chankey) {
- return InvalidChannel;
- }
-
- return OK;
-}
-
-
-static int Go_syst_err_11(gchar** response, int channel, char *parameter,char *units,int command_type)
-{
- switch (command_type) {
- case query_simple:
- if (globals.number_of_errors==0) {
- get_error_text(response, OK);
- } else {
- get_error_text(response,globals.error_queue[1]);
- Error_Remove_From_Queue();
- }
- return OK;
- break;
-
- default:
- return SyntaxError;
- break;
- }
-}
-
-static int Go_syst_errcnt66(gchar** response, int channel, char *parameter,char *units,int command_type)
-{
- switch (command_type) {
- case query_simple:
- return query_int (response, globals.number_of_errors);
- break;
-
- default:
- return SyntaxError;
- break;
- }
-}
-
+/* START LIBRARY DESCRIPTION ********************************************* +PARSER.LIB + Copyright (c) 1997, Avtech Electrosystems Ltd. + +DESCRIPTION: + Parser functions. + +SUPPORT LIB'S: +END DESCRIPTION **********************************************************/ + + +#include "parser.h" +#include <glib/gprintf.h> + +//STATICS +static int query_int (gchar** response, int n); +static int query_min_max_float (gchar** response, char *parameter, float min_val, float max_val); +static int query_float (gchar** response, float value); +static int process_float_param (char *parameter, float *value, float min_val, float max_val, int zero_mode); +static int check_channel_ok (int channel, int enabled_channels, char chankey); +static int Parser_id_word(char *id_me, int *channel, int *with_id_code); +static int Parser_find_commands(int commands[], int command_depth); +static int Parser_get_unit(char **parameter, char **units); +static int Parser_channel (int *channel,int with_id_code,int routine_num); +static int Go_freq_32_33(gchar** response, int channel, char *parameter,char *units,int command_type); +static int Handle_Units(float *mult,char *units, char *base); +static int Is_Min_Command(char *text); +static int Is_Max_Command(char *text); +static int Go_syst_err_11(gchar** response, int channel, char *parameter,char *units,int command_type); +static int Go_syst_errcnt66(gchar** response, int channel, char *parameter,char *units,int command_type); + +static int Parser_id_word(char *id_me, int *channel, int *with_id_code) +{ + int id_code; + int set_new_channel; + + set_new_channel=0; + + /* detect channel suffixes in the range of 0-99 */ + if (isdigit((int) id_me[strlen(id_me)-1])) { + set_new_channel=1; + *channel=atoi(id_me+strlen(id_me)-1); + if (isdigit((int) id_me[strlen(id_me)-2])) { + *channel=atoi(id_me+strlen(id_me)-2); + id_me[strlen(id_me)-2]=0; + } else { + id_me[strlen(id_me)-1]=0; + } + } + + + if (!strcmp(id_me,"*cls") ) { + id_code = 1; + } else if (!strcmp(id_me,"*ese") ) { + id_code = 2; + } else if (!strcmp(id_me,"*esr") ) { + id_code = 4; + } else if (!strcmp(id_me,"*idn") ) { + id_code = 5; + } else if (!strcmp(id_me,"*opc") ) { + id_code = 6; + } else if (!strcmp(id_me,"*rst") ) { + id_code = 8; + } else if (!strcmp(id_me,"*sre") ) { + id_code = 9; + } else if (!strcmp(id_me,"*stb") ) { + id_code = 10; + } else if (!strcmp(id_me,"*tst") ) { + id_code = 11; + } else if (!strcmp(id_me,"*wai") ) { + id_code = 12; + } else if (!strcmp(id_me,"system") || !strcmp(id_me,"syst")) { + id_code = 13; + } else if (!strcmp(id_me,"error") || !strcmp(id_me,"err")) { + id_code = 14; + } else if (!strcmp(id_me,"version") || !strcmp(id_me,"vers")) { + id_code = 15; + } else if (!strcmp(id_me,"status") || !strcmp(id_me,"stat") || !strcmp(id_me,"state")) { + id_code = 16; + } else if (!strcmp(id_me,"operation") || !strcmp(id_me,"oper")) { + id_code = 17; + } else if (!strcmp(id_me,"event") || !strcmp(id_me,"even")) { + id_code = 18; + } else if (!strcmp(id_me,"condition") || !strcmp(id_me,"cond")) { + id_code = 19; + } else if (!strcmp(id_me,"enable") || !strcmp(id_me,"enab")) { + id_code = 20; + } else if (!strcmp(id_me,"questionable") || !strcmp(id_me,"ques")) { + id_code = 21; + } else if (!strcmp(id_me,"preset") || !strcmp(id_me,"pres")) { + id_code = 22; + } else if (!strcmp(id_me,"diagnostic") || !strcmp(id_me,"diag")) { + id_code = 23; + } else if (!strcmp(id_me,"output") || !strcmp(id_me,"outp")) { + id_code = 24; + } else if (!strcmp(id_me,"impedance") || !strcmp(id_me,"imp")) { + id_code = 25; + } else if (!strcmp(id_me,"protection") || !strcmp(id_me,"prot")) { + id_code = 26; + } else if (!strcmp(id_me,"tripped") || !strcmp(id_me,"trip")) { + id_code = 27; + } else if (!strcmp(id_me,"source") || !strcmp(id_me,"sour")) { + id_code = 28; + } else if (!strcmp(id_me,"current") || !strcmp(id_me,"curr")) { + id_code = 29; + } else if (!strcmp(id_me,"level") || !strcmp(id_me,"lev")) { + id_code = 30; + } else if (!strcmp(id_me,"immediate") || !strcmp(id_me,"imm")) { + id_code = 31; + } else if (!strcmp(id_me,"amplitude") || !strcmp(id_me,"ampl")) { + id_code = 32; + } else if (!strcmp(id_me,"offset") || !strcmp(id_me,"offs")) { + id_code = 33; + } else if (!strcmp(id_me,"high") ) { + id_code = 34; + } else if (!strcmp(id_me,"low") ) { + id_code = 35; + } else if (!strcmp(id_me,"voltage") || !strcmp(id_me,"volt")) { + id_code = 36; + } else if (!strcmp(id_me,"frequency") || !strcmp(id_me,"freq")) { + id_code = 37; + } else if (!strcmp(id_me,"function") || !strcmp(id_me,"func")) { + id_code = 38; + } else if (!strcmp(id_me,"shape") || !strcmp(id_me,"shap")) { + id_code = 39; + } else if (!strcmp(id_me,"pulse") || !strcmp(id_me,"puls")) { + id_code = 40; + } else if (!strcmp(id_me,"period") || !strcmp(id_me,"per")) { + id_code = 41; + } else if (!strcmp(id_me,"width") || !strcmp(id_me,"widt")) { + id_code = 42; + } else if (!strcmp(id_me,"dcycle") || !strcmp(id_me,"dcyc")) { + id_code = 43; + } else if (!strcmp(id_me,"hold") ) { + id_code = 44; + } else if (!strcmp(id_me,"delay") || !strcmp(id_me,"del")) { + id_code = 45; + } else if (!strcmp(id_me,"double") || !strcmp(id_me,"doub")) { + id_code = 46; + } else if (!strcmp(id_me,"polarity") || !strcmp(id_me,"pol")) { + id_code = 47; + } else if (!strcmp(id_me,"beeper") || !strcmp(id_me,"beep")) { + id_code = 48; + } else if (!strcmp(id_me,"cw") ) { + id_code = 49; + } else if (!strcmp(id_me,"fixed") || !strcmp(id_me,"fix")) { + id_code = 50; + } else if (!strcmp(id_me,"abort") || !strcmp(id_me,"abor")) { + id_code = 51; + } else if (!strcmp(id_me,"initiate") || !strcmp(id_me,"init")) { + id_code = 52; + } else if (!strcmp(id_me,"continuous")) { + id_code = 53; + } else if (!strcmp(id_me,"trigger") || !strcmp(id_me,"trig")) { + id_code = 54; + } else if (!strcmp(id_me,"integer") || !strcmp(id_me,"int")) { + id_code = 55; + } else if (!strcmp(id_me,"float") ) { + id_code = 56; + } else if (!strcmp(id_me,"eprom") ) { + id_code = 57; + } else if (!strcmp(id_me,"string") ) { + id_code = 58; + } else if (!strcmp(id_me,"bit") ) { + id_code = 59; + } else if (!strcmp(id_me,"set") ) { + id_code = 60; + } else if (!strcmp(id_me,"clear") ) { + id_code = 61; + } else if (!strcmp(id_me,"shiftreg") ) { + id_code = 62; + } else if (!strcmp(id_me,"*rcl") ) { + id_code = 63; + } else if (!strcmp(id_me,"*sav") ) { + id_code = 64; + } else if (!strcmp(id_me,"gate") ) { + id_code = 65; + } else if (!strcmp(id_me,"local") || !strcmp(id_me,"logout") || !strcmp(id_me,"exit") || !strcmp(id_me,"quit") ) { + id_code = 66; + } else if (!strcmp(id_me,"test") ) { + id_code = 67; + } else if (!strcmp(id_me,"communicate") || !strcmp(id_me,"comm")) { + id_code = 68; + } else if (!strcmp(id_me,"address") || !strcmp(id_me,"addr")) { + id_code = 69; + } else if (!strcmp(id_me,"gpib") ) { + id_code = 70; + } else if (!strcmp(id_me,"serial") || !strcmp(id_me,"ser")) { + id_code = 71; + } else if (!strcmp(id_me,"receive") || !strcmp(id_me,"rec")) { + id_code = 72; + } else if (!strcmp(id_me,"baud") ) { + id_code = 73; + } else if (!strcmp(id_me,"parity") || !strcmp(id_me,"par")) { + id_code = 74; + } else if (!strcmp(id_me,"type") ) { + id_code = 75; + } else if (!strcmp(id_me,"bits") ) { + id_code = 76; + } else if (!strcmp(id_me,"sbits") || !strcmp(id_me,"sbit")) { + id_code = 77; + } else if (!strcmp(id_me,"echo") ) { + id_code = 78; + } else if (!strcmp(id_me,"rts") ) { + id_code = 79; + } else if (!strcmp(id_me,"control") || !strcmp(id_me,"cont")) { + id_code = 80; + } else if (!strcmp(id_me,"next") ) { + id_code = 81; + } else if (!strcmp(id_me,"count") || !strcmp(id_me,"coun")) { + id_code = 82; + } else if (!strcmp(id_me,"display") || !strcmp(id_me,"disp")) { + id_code = 83; + } else if (!strcmp(id_me,"brightness") || !strcmp(id_me,"brig")) { + id_code = 84; + } else if (!strcmp(id_me,"load") ) { + id_code = 85; + } else if (!strcmp(id_me,"measure") || !strcmp(id_me,"meas")) { + id_code = 86; + } else if (!strcmp(id_me,"char") ) { + id_code = 87; + } else if (!strcmp(id_me,"calibration") || !strcmp(id_me,"cal")) { + id_code = 88; + } else if (!strcmp(id_me,"monitor") || !strcmp(id_me,"mon")) { + id_code = 89; + } else if (!strcmp(id_me,"step") ) { + id_code = 90; + } else if (!strcmp(id_me,"route") || !strcmp(id_me,"rout")) { + id_code = 91; + } else if (!strcmp(id_me,"close") || !strcmp(id_me,"clos")) { + id_code = 92; + } else if (!strcmp(id_me,"point") ) { + id_code = 93; + } else if (!strcmp(id_me,"shift") ) { + id_code = 94; + } else if (!strcmp(id_me,"scale") ) { + id_code = 95; + } else if (!strcmp(id_me,"null") ) { + id_code = 96; + } else if (!strcmp(id_me,"size") ) { + id_code = 97; + } else if (!strcmp(id_me,"separation") || !strcmp(id_me,"sep")) { + id_code = 98; + } else if (!strcmp(id_me,"network") || !strcmp(id_me,"net")) { + id_code = 99; + } else if (!strcmp(id_me,"password") || !strcmp(id_me,"pass")) { + id_code = 100; + } else if (!strcmp(id_me,"new") ) { + id_code = 101; + } else if (!strcmp(id_me,"suspend") ) { + id_code = 102; + } else if (!strcmp(id_me,"transition") || !strcmp(id_me,"tran")) { + id_code = 103; + } else if (!strcmp(id_me,"leading") || !strcmp(id_me,"lead")) { + id_code = 104; + } else if (!strcmp(id_me,"limit") || !strcmp(id_me,"lim")) { + id_code = 105; + } else if (!strcmp(id_me,"slew") ) { + id_code = 106; + } else if (!strcmp(id_me,"all") ) { + id_code = 107; + } + + else { + id_code = 9999; + } + + if (set_new_channel) { + *with_id_code=id_code; + } + + return id_code; + +} + +static int Parser_find_commands(int commands[], int command_depth) +{ +#define optional 16384 /* set bit high if optional */ +#define opt_mask 16383 /* default bit mask */ +#define max_tokens_in_sentence 7 +#define max_no_of_sentences 110 + + /* Valid command -sequences-. The -individual- commands are defined in id_word. */ + + static const int sentences[max_no_of_sentences][max_tokens_in_sentence] = { + {0}, /* null - error */ + {1}, /* cls - sentence 1 */ + {2}, /* ese - sentence 2 */ + {4}, /* esr - sentence 3 */ + {5}, /* idn - sentence 4 */ + {6}, /* opc - sentence 5 */ + {8}, /* rst - sentence 6 */ + {9}, /* sre - sentence 7 */ + {10}, /* stb - sentence 8 */ + {11}, /* tst - sentence 9 */ + {12}, /* wai - sentence 10 */ + {13,14,81|optional}, /* syst:err:next - 11 */ + {13,15}, /* syst:vers - 12 */ + {16,17,18|optional}, /* stat:oper:event - 13 */ + {16,17,19}, /* stat:oper:cond - 14 */ + {16,17,20}, /* stat:oper:enable - 15 */ + {16,21,18|optional}, /* stat:ques:event - 16 */ + {16,21,19}, /* stat:ques:cond - 17 */ + {16,21,20}, /* stat:ques:enable - 18 */ + {16,22}, /* stat:preset - 19 */ + {24,25}, /* output:impedance - 20 */ + {24,26,27}, /* output:prot:tripped - 21 */ + {28|optional,29,30|optional,31|optional,32|optional}, /* sour:curr:lev:imm:ampl - 22 */ + {28|optional,29,30|optional,31|optional,33}, /* sour:curr:lev:imm:offset - 23 - not used */ + {28|optional,29,30|optional,31|optional,34}, /* sour:curr:lev:imm:high - 24 - not used */ + {28|optional,29,30|optional,31|optional,35}, /* sour:curr:lev:imm:low - 25 */ + {28|optional,36,30|optional,31|optional,32|optional}, /* sour:volt:lev:imm:ampl - 26 */ + {28|optional,36,30|optional,31|optional,33}, /* sour:volt:lev:imm:offset - 27 - not used */ + {28|optional,36,30|optional,31|optional,34}, /* sour:volt:lev:imm:high - 28 - not used */ + {28|optional,36,30|optional,31|optional,35}, /* sour:volt:lev:imm:low - 29 */ + {28|optional,29,26,27}, /* sour:curr:prot:tripped? - 30 */ + {28|optional,36,26,27}, /* sour:volt:prot:tripped? - 31 */ + {28|optional,37,49|optional}, /* sour:freq:cw - 32 */ + {28|optional,37,50|optional}, /* sour:freq:fixed - 33 */ + {28|optional,38,39|optional}, /* sour:func:shape - 34 */ + {28|optional,40,41}, /* sour:puls:per - 35 */ + {28|optional,40,42}, /* sour:puls:width - 36 */ + {28|optional,40,43}, /* sour:puls:dcyc - 37 */ + {28|optional,40,44}, /* sour:puls:hold - 38 */ + {28|optional,40,45}, /* sour:puls:delay - 39 */ + {28|optional,40,46,16|optional}, /* sour:puls:doub:state - 40 */ + {28|optional,40,46,45}, /* sour:puls:doub:delay - 41 */ + {28|optional,40,47}, /* sour:puls:pol - 42 */ + {13,48,31|optional}, /* syst:beep:imm - 43 - not used */ + {52,31|optional,53}, /* init:imm:cont - 44 - not used */ + {51}, /* abort - 45 - not used */ + {54,31|optional,28}, /* trig:imm:sour - 46 */ + {23,57,58}, /* diag:eprom:string - 47 */ + {23,57,55}, /* diag:eprom:int - 48 */ + {23,57,59,60}, /* diag:eprom:bit:set - 49 - not used */ + {23,57,59,61}, /* diag:eprom:bit:clear - 50 - not used */ + {23,57,56}, /* diag:eprom:float - 51 */ + {23,62}, /* diag:shiftreg - 52 */ + {63}, /* *rcl - 53 */ + {64}, /* *sav - 54 */ + {24,16|optional}, /* output:state - 55 */ + {28|optional,40,65,75}, /* sour:puls:gate:type - 56 */ + {66}, /* local (RS232 mode only) - 57 */ + {23,67,45}, /* diag:test:delay - 58 */ + {13,68,70,69}, /* syst:comm:gpib:addr - 59 */ + {13,68,71,72|optional,73}, /* syst:comm:ser:rec:baud - 60 */ + {13,68,71,72|optional,74,75|optional}, /* syst:comm:ser:rec:parity - 61 */ + {13,68,71,72|optional,76}, /* syst:comm:ser:rec:bits - 62 */ + {13,68,71,72|optional,77}, /* syst:comm:ser:rec:sbits - 63 */ + {13,68,71,80,79}, /* syst:comm:ser:control:rts - 64 */ + {13,68,71,72|optional,78}, /* syst:comm:ser:rec:echo - 65 */ + {13,14,82}, /* syst:err:count - 66 */ + {28|optional,40,65,30}, /* sour:puls:gate:level - 67 */ + {24,85}, /* output:load - 68 */ + {86,32}, /* meas:ampl? - 69 */ + {23,57,87}, /* diag:eprom:char - 70 */ + {23,88}, /* diag:calib - 71 */ + {23,32,88,95|optional}, /* diag:ampl:calib:scale - 72 */ + {23,89,88,95|optional}, /* diag:mon:calib:scale - 73 */ + {23,89,90}, /* diag:mon:step - 74 */ + {24,75}, /* output:type - 75 */ + {23,33,88,95|optional}, /* diag:offset:calib:scale - 76 */ + {23,40,42,88,94}, /* diag:pulse:width:calib:shift - 77 */ + {91,92}, /* route:close - 78 */ + {23,40,42,88,93}, /* diag:pulse:width:calib:point - 79 */ + {23,40,45,88,93}, /* diag:pulse:delay:calib:point - 80 */ + {23,40,41,88,93}, /* diag:pulse:period:calib:point - 81 */ + {23,40,45,88,94}, /* diag:pulse:delay:calib:shift - 82 */ + {23,32,88,93}, /* diag:ampl:calib:point - 83 */ + {23,33,88,93}, /* diag:offset:calib:point - 84 */ + {23,33,96,93}, /* diag:offset:null:point - 85 */ + {23,57,97}, /* diag:eprom:size - 86 */ + {83,84}, /* display:brightness - 87 */ + {28|optional,40,82}, /* sour:puls:count - 88 */ + {28|optional,40,98}, /* sour:puls:separation - 89 */ + {23,40,98,88,93}, /* diag:pulse:separation:calib:point - 90 */ + {13,68,99}, /* system:comm:network - 91 */ + {13,100,101}, /* system:password:new - 92 */ + {23,57,102}, /* diag:eprom:suspend - 93 */ + {28|optional,40,103,104|optional}, /* sour:puls:transition:leading - 94 */ + {23,40,103,88,93}, /* diag:pulse:transition:calib:point - 95 */ + {28|optional,29,105,32|optional}, /* sour:curr:limit:ampl - 96 */ + {23,24,85,88,93}, /* diag:output:load:calib:point - 97 */ + {28|optional,29,106}, /* sour:curr:slew - 98 */ + {23,106,88,93}, /* diag:slew:calib:point - 99 */ + {88,107|optional}, /* calibration:all - 100 */ + {88,37} /* calibration:frequency - 101 */ + + }; + + + int token_num; /* which token in the command[] list is being considered */ + int sentence_num; /* which sentence is being considered as a match */ + int sentence_found; /* matching sentence found yet? */ + int sent_pos; /* position in current sentence */ + int invalid_match; /* flag if definitely the wrong match */ + int local_match_pos; /* position (or pos+1, depends) of most-recently-matched token in sentence */ + int local_match; /* match for current token found yet? */ + int prev_match; /* were there previous local matches? */ + int i; /* a counter */ + + sentence_num = 1; + sent_pos = 0; + + /* check each "sentence" (corresponding to a different routine or function) + until a match is found, or until their are no possible sentences left */ + for (sentence_found = 0; (!sentence_found && sentence_num < max_no_of_sentences); ++sentence_num) { + local_match_pos=0; + invalid_match=0; + prev_match=0; + /* start with the first input token, until all have been matched, or one + is unmatchable */ + for (token_num = 0; (token_num < command_depth) && !invalid_match; ++token_num) { + /* start after most recent matching token */ + sent_pos=local_match_pos; + + /* compare current token to the sentence components until a matching component + is found, or until there are none left */ + for (local_match=0; (!local_match) && (sent_pos<max_tokens_in_sentence); ++sent_pos) { + + /* compare here */ + if (commands[token_num]==((sentences[sentence_num][sent_pos]) & opt_mask)) { + /* flag a local token match (not a whole sentence match) */ + local_match=1; + } + } + if (local_match) { + /* if any of the components in the sentence were skipped between the last two + matches, make sure that they were optional ones */ + if (!prev_match) { + local_match_pos=-1; + } + /* if there was no local match previously, then the initial value + of local_match_pos is misleading - there was no match at 0. */ + for (i=(local_match_pos+1); i<(sent_pos-1); ++i) { + /* if they weren't optional, the match is not valid */ + if (!(sentences[sentence_num][i] & optional)) { + invalid_match=1; + } + } + /* counteract the last "++i" due to the for loop */ + local_match_pos = sent_pos - 1; + if (local_match && !invalid_match) { + prev_match=1; + } + } + + /* if no match for this one token existed in this sentence, mark this sentence as invalid */ + if (!local_match) { + invalid_match = 1; + } + } + /* if no invalid token match was found for any of the tokens in this sentence, + then it's an overall sentence match! */ + if (!invalid_match) { + sentence_found=1; + } + } + --sentence_num; + + if (!sentence_found) { + sentence_num = 0; + } + /* 0 is the no-match value */ + + return sentence_num; +} + + +static int Parser_get_unit(char **parameter, char **units) +{ + /* this function takes a parameter like "1e+6 ms" and breaks it into parameter="1e+6" and + units="ms" */ + + if (*parameter == NULL) { + *parameter = g_strdup (""); + } + + g_assert (*units == NULL); + + gchar *end_ptr; + g_strtod (*parameter, &end_ptr); + + if (end_ptr == *parameter) { + *units = g_strdup (""); + } else { + *units = g_strdup (end_ptr); + end_ptr[0] = 0; // truncates parameter + } + + g_strstrip (*units); + g_strstrip (*parameter); + + int units_present = (*units[0] != 0); + return units_present; +} + +void Parser_main (char *raw_in, int interactive_terminal, void(*cbfunc)(gpointer, gchar *), gpointer user_data) +{ + int in_pos; /* this identifies the single character of in being processed */ + int command_depth; /* how many command words have been parsed */ + int old_command_depth; /* save this if in case of a compound message */ + char current_command[max_input_word_length]; /* current command word being processed */ + int current_command_length; /* length of current command so far */ + int commands[max_commands_in_input]; /* list of identified command tokens */ + int old_commands[max_commands_in_input]; /* list of identified command tokens from */ + /* last non-common, non-colon-started command*/ + int space_found; /* if true, a space was found. parameter may follow */ + int parameter_found; /* if true, there is a parameter at the end of the command string */ + int semicolon_found; /* to break up lines */ + int units_found; /* text found after parameter must be units */ + int i; /* counter */ + int routine_num; /* routine to execute, based on command */ + int dont_use_this_header; /* the old head is saved in case of compound message, unless this is set */ + int compound_message; /* this indicates that at least one semicolon has been found, so */ + /* the message is a compound one */ + + + int is_query; + int command_type; /* combination of is_query, parameter_found, and units_found */ + + int channel; + int with_id_code; + + g_strstrip (raw_in); + + // add white space to the end of the input string - FIXME? + gchar *in = g_strdup_printf ("%s ", raw_in); + + in_pos = 0; /* start at the beginning of the input string */ + semicolon_found = 0; + compound_message = 0; + command_depth=0; + old_command_depth=0; + dont_use_this_header=NO; + + while (isspace(in[in_pos]) || in[in_pos]==':' || in[in_pos]==';') { + /* ignore leading spaces */ + ++in_pos; + } + + + /* examine each letter in the string until EOS */ + while (in[in_pos] != 0) { + + gchar *units = NULL; + gchar *response = NULL; + gchar *error_response = NULL; + gchar *parameter = NULL; + + channel=-1; + with_id_code=0; + space_found = 0; + parameter_found = 0; /* no numeric parameters yet */ + units_found = 0; + is_query = 0; + current_command_length = 0; + + if (semicolon_found && !dont_use_this_header) { + old_command_depth=command_depth-2; + for (i=0; i<old_command_depth; ++i) { + old_commands[i]=commands[i]; + } + } + + command_depth=old_command_depth; + for (i=0; i<command_depth; ++i) { + commands[i]=old_commands[i]; + } + + semicolon_found=0; + dont_use_this_header=NO; + + /* break it up if semicolons are present */ + while (!semicolon_found && in[in_pos] != 0) { + + in[in_pos]=tolower(in[in_pos]); + /* everything to lowercase */ + + /* words are separated by white space or colons or semicolons */ + if ( isspace(in[in_pos]) || in[in_pos] == ':' || in[in_pos] == ';') + + { + + if (in[in_pos] == ';') { + ++semicolon_found; + } + ++compound_message; + + /* if it is a separator, ignore it if it is duplicated */ + if ( !isspace(in[in_pos-1]) && (in[in_pos-1] != ':') && (in[in_pos-1] != ';')) { + /* valid separator, so terminate current command word string */ + current_command[current_command_length] = '\0'; + + if (space_found) { + /* Just end things if it is a semicolon */ + if (in[in_pos]!=';') { + current_command[current_command_length] = in[in_pos]; + ++current_command_length; + } + + current_command[current_command_length] = '\0'; + ++parameter_found; + parameter = g_strdup (current_command); + } else if (!space_found) { + /* just a regular command word */ + + /* terminate the current command string */ + current_command_length = 0; /* make room for a new command string */ + commands[command_depth]=Parser_id_word(current_command,&channel,&with_id_code); + + if ( commands[command_depth]<13 + || commands[command_depth]==63 + || commands[command_depth]==64) { + dont_use_this_header=YES; + commands[0]=commands[command_depth]; + command_depth=0; + } + + ++command_depth; /* indicate that a new command word is ready */ + + /* indicate if the separator was a space - next bit parameter then */ + if (in[in_pos]==' ') { + ++space_found; + } + } + } /* non-repeated separator */ + else if (compound_message && in[in_pos-1]==';' && in[in_pos]==':') { + dont_use_this_header=YES; + command_depth=0; + } + + } /* a separator */ + else if (in[in_pos]!='?') { + /* if not white space or separator, add character to current command word */ + current_command[current_command_length] = in[in_pos]; + ++current_command_length; + } /* not a separator */ + else { + ++is_query; + /* question mark found */ + } + + + ++in_pos; /* move pointer to next letter */ + + } /* not a semi-colon */ + + commands[command_depth]=0; + ++command_depth; + /* add end of tokens marker (0) */ + + int error_num=OK; + + units_found = Parser_get_unit(¶meter,&units); + + if (!error_num) { + command_type=(is_query<<2) | (parameter_found?2:0) | units_found; + + if (commands[0]!=0) { + routine_num = Parser_find_commands(commands,command_depth); + + /* check for valid channel number, based on position in command */ + if ( (error_num=Parser_channel(&channel,with_id_code,routine_num)) ) + /* not a valid command due to improper channel suffix */ + { + routine_num=9999; + } + } else { + routine_num=9999; + /* ignore empty commands lists, generated by a white space string */ + } + + switch (routine_num) { + case 0: + response = g_strdup_printf("routine_num: %d, channel: %d, parameter: %s, units: %s, command type: %d",routine_num,channel,parameter,units,command_type); + error_num=Unrecognized; + break; + case 11: + error_num=Go_syst_err_11(&response,channel,parameter,units,command_type); + break; + case 32: + case 33: + error_num=Go_freq_32_33(&response,channel,parameter,units,command_type); + break; + case 66: + error_num=Go_syst_errcnt66(&response,channel,parameter,units,command_type); + break; + + case 9999: + // was only whitespace, ignore + break; + + default: + /* valid but not implemented yet */ + response = g_strdup_printf("routine_num: %d, channel: %d, parameter: %s, units: %s, command type: %d",routine_num,channel,parameter,units,command_type); + break; + + } + } + + if (error_num) { + queue_error_from_parser(&error_response, error_num); + if (interactive_terminal) { + (*cbfunc)(user_data, error_response); + } + } else { + (*cbfunc)(user_data, response); + } + + g_free (units); + g_free (response); + g_free (error_response); + g_free (parameter); + + if (!is_query) { + Main_update_shift_registers(); /* update values in pulse generator circuit */ + } + + } /* not EOS */ + + /* update display if it wasn't a query, and if the control menu isn't on (this gives the user + a chance to press "Go To Local" to override control */ + + int Selected_Submenu=0, Submenu1_rem_loc=0, Type_Of_Menu=0, Submenu_On=0; + + if (!is_query && !(Selected_Submenu==Submenu1_rem_loc && Type_Of_Menu==Submenu_On)) { + Menu_Update_Display(); + } + + /* re-run error_check to update min/max values based on actual settings, not proposed settings */ + Error_check(globals.ChannelState); + + // trigger a prompt + if (interactive_terminal) { + (*cbfunc)(user_data, ""); + } + + g_free (in); +} + + +static int Parser_channel (int *channel,int with_id_code,int routine_num) +{ + /* return if no channel suffixes appeared */ + if (*channel==-1) { + *channel=0; + return OK; + } + + + /* compare to maximum number of channels allowed */ + if (*channel>1 && *channel>globals.Flash.channels && !globals.Flash.enable_avrq_extra_ampls) { + return InvalidChannel; + } + if (*channel>5 && globals.Flash.enable_avrq_extra_ampls) { + return InvalidChannel; + } + + + /* SCPI uses 1-N counting, change to 0 - (N-1) */ + if (*channel > 0) { + --(*channel); + } else { + return InvalidChannel; + } + + return OK; +} + + +static int Go_freq_32_33(gchar** response, int channel, char *parameter,char *units,int command_type) +{ + // this is a typical parser function - there will be many more added later + + float new_freq; + int status; + + if ( (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_frequency))) { + return status; + } + + new_freq=1.0; + + switch (command_type) { + case command_param_units: + if ( (status=Handle_Units(&new_freq,units,"hz")) ) { + return status; + } + /* no break */ + + case command_withparam: + if ( (status = process_float_param (parameter, &new_freq, 1.0, 1.0e6, NORMAL_ZERO)) ) { + return status; + } + return Set_frequency(0,0,0,channel,new_freq); + break; + + case query_simple: + return query_float(response, globals.ChannelState[channel].frequency); + break; + + case query_param: + return query_min_max_float (response, parameter, 1.0, 1.0e6); + break; + + default: + return SyntaxError; + break; + } +} + + +static int Handle_Units(float *mult,char *units, char *in_base) +{ + int len_base, len_all, pos; + char prefix[max_input_word_length]; + char base[max_input_word_length]; + + strcpy (base, in_base); + + *mult=1.0; + if (!strcmp(units,base)) { + return OK; + } + + // match base + len_all = strlen (units); + if (len_all == 0) { + return OK; + } + + len_base = strlen (base); + pos = len_all - len_base; + + strcpy (prefix, units); + + if (!strcmp(base,"%") && (len_all >= 3) && !strcmp(prefix + len_all - 3,"pct")) { + strcpy(base, "pct"); + prefix[len_all - 3] = 0; + } else if (!strcmp(base,"pct") && !strcmp(prefix + len_all - 1,"%")) { + strcpy(base, "%"); + prefix[len_all - 1] = 0; + } else if (strcmp(prefix+pos,base)) { + return UnknownUnits; + } else { + prefix[pos]=0; + } + + if (strlen(prefix) == 0) { + return OK; + } + + // special exceptions + if (!strcmp(prefix,"m") && !strcmp(base,"ohm")) { + *mult=1.0e6; + } else if (!strcmp(prefix,"m") && !strcmp(base,"hz")) { + *mult=1.0e6; + } + // normal rules + else if (!strcmp(prefix,"ex")) { + *mult=1.0e18; + } else if (!strcmp(prefix,"pe")) { + *mult=1.0e15; + } else if (!strcmp(prefix,"t")) { + *mult=1.0e12; + } else if (!strcmp(prefix,"g")) { + *mult=1.0e9; + } else if (!strcmp(prefix,"ma")) { + *mult=1.0e6; + } else if (!strcmp(prefix,"k")) { + *mult=1.0e3; + } else if (!strcmp(prefix,"m")) { + *mult=1.0e-3; + } else if (!strcmp(prefix,"u")) { + *mult=1.0e-6; + } else if (!strcmp(prefix,"n")) { + *mult=1.0e-9; + } else if (!strcmp(prefix,"p")) { + *mult=1.0e-12; + } else if (!strcmp(prefix,"f")) { + *mult=1.0e-15; + } else if (!strcmp(prefix,"a")) { + *mult=1.0e-18; + } else { + return UnknownUnits; + } + + return OK; +} + + +static int Is_Min_Command(gchar *text) +{ + return (!strcmp(text,"min") || !strcmp(text,"minimum")); +} + + +static int Is_Max_Command(char *text) +{ + return (!strcmp(text,"max") || !strcmp(text,"maximum")); +} + +static int query_int (gchar** response, int n) +{ + *response = g_strdup_printf ("%d", n); + return OK; +} + +static int query_min_max_float (gchar** response, char *parameter, float min_val, float max_val) +{ + float report_val; + + if (Is_Min_Command(parameter)) { + report_val=min_val; + } else if (Is_Max_Command(parameter)) { + report_val=max_val; + } else { + return SyntaxError; + } + + Float_To_Text(remote_digits_after_decimal,report_val,response); + return OK; +} + +static int query_float (gchar** response, float value) +{ + Float_To_Text(remote_digits_after_decimal,value,response); + return OK; +} + +static int process_float_param (char *parameter, float *value, float min_val, float max_val, int zero_mode) +{ + int status; + status = OK; + + if (String_is_it_numeric(parameter)) { + *value *= atof(parameter); + + if (zero_mode == ALLOW_NEG_ZERO) { + /* allow a value of "-0" */ + if (fabs(*value) < smallest_allowed_number) + if (parameter[0] == '-') { + *value = -0.1*smallest_allowed_number; + } + } + } + + else if (!strcmp(parameter,"+") && (zero_mode == ALLOW_NEG_ZERO)) { + *value = smallest_allowed_number; + } else if (!strcmp(parameter,"-") && (zero_mode == ALLOW_NEG_ZERO)) { + *value = -smallest_allowed_number; + } else if (Is_Min_Command(parameter)) { + *value = min_val; + } else if (Is_Max_Command(parameter)) { + *value = max_val; + } else { + status=SyntaxError; + } + + return status; +} + +static int check_channel_ok (int channel, int enabled_channels, char chankey) +{ + /* how many channels overall */ + if (channel >= enabled_channels) { + return InvalidChannel; + } + + /* abandon if high channel selected by user but not enabled by firmware for that parameter*/ + if (channel && !chankey) { + return InvalidChannel; + } + + return OK; +} + + +static int Go_syst_err_11(gchar** response, int channel, char *parameter,char *units,int command_type) +{ + switch (command_type) { + case query_simple: + if (globals.number_of_errors==0) { + get_error_text(response, OK); + } else { + get_error_text(response,globals.error_queue[1]); + Error_Remove_From_Queue(); + } + return OK; + break; + + default: + return SyntaxError; + break; + } +} + +static int Go_syst_errcnt66(gchar** response, int channel, char *parameter,char *units,int command_type) +{ + switch (command_type) { + case query_simple: + return query_int (response, globals.number_of_errors); + break; + + default: + return SyntaxError; + break; + } +} + diff --git a/string_utils.c b/string_utils.c index e28ccfc..db077a7 100644 --- a/string_utils.c +++ b/string_utils.c @@ -1,48 +1,48 @@ -/* START LIBRARY DESCRIPTION *********************************************
-FLOAT.LIB
- Copyright (c) 2006, Avtech Electrosystems Ltd.
-
-DESCRIPTION:
- Functions that deal with strings and floating point numbers.
-
-SUPPORT LIB'S:
-END DESCRIPTION **********************************************************/
-
-
-#include <string.h>
-#include <ctype.h>
-#include <math.h>
-#include <glib/gprintf.h>
-#include "globals.h"
-#include "string_utils.h"
-
-void Float_To_Text(int decimal_digits,float number_in, gchar ** text_out)
-{
- g_assert (*text_out == NULL);
-
- if (fabs(number_in)<1.1*smallest_allowed_number) {
- if (number_in<0.0) {
- *text_out = g_strdup_printf("-0.%0*d",decimal_digits,0);
- } else {
- *text_out = g_strdup_printf("0.%0*d",decimal_digits,0);
- }
- return;
- }
-
- *text_out = g_strdup_printf("%.*e", decimal_digits, number_in);
-}
-
-
-/*----------------------------------------------------------------------------------------------------------*/
-gboolean String_is_it_numeric(char *parameter)
-{
-
- GRegex *numeric_regex = g_regex_new ( "\\s*[+-]?(\\d*\\.\\d+|\\d+(\\.\\d*)?)\\s*(e\\s*[+-]?\\d+)?\\s*",
- G_REGEX_CASELESS,
- 0,
- NULL);
-
- gboolean match = g_regex_match (numeric_regex, parameter, 0, NULL);
- g_regex_unref (numeric_regex);
- return match;
-}
+/* START LIBRARY DESCRIPTION ********************************************* +FLOAT.LIB + Copyright (c) 2006, Avtech Electrosystems Ltd. + +DESCRIPTION: + Functions that deal with strings and floating point numbers. + +SUPPORT LIB'S: +END DESCRIPTION **********************************************************/ + + +#include <string.h> +#include <ctype.h> +#include <math.h> +#include <glib/gprintf.h> +#include "globals.h" +#include "string_utils.h" + +void Float_To_Text(int decimal_digits,float number_in, gchar ** text_out) +{ + g_assert (*text_out == NULL); + + if (fabs(number_in)<1.1*smallest_allowed_number) { + if (number_in<0.0) { + *text_out = g_strdup_printf("-0.%0*d",decimal_digits,0); + } else { + *text_out = g_strdup_printf("0.%0*d",decimal_digits,0); + } + return; + } + + *text_out = g_strdup_printf("%.*e", decimal_digits, number_in); +} + + +/*----------------------------------------------------------------------------------------------------------*/ +gboolean String_is_it_numeric(char *parameter) +{ + + GRegex *numeric_regex = g_regex_new ( "\\s*[+-]?(\\d*\\.\\d+|\\d+(\\.\\d*)?)\\s*(e\\s*[+-]?\\d+)?\\s*", + G_REGEX_CASELESS, + 0, + NULL); + + gboolean match = g_regex_match (numeric_regex, parameter, 0, NULL); + g_regex_unref (numeric_regex); + return match; +} |