Fix OUR_strndup, optimize non USE_DEVICE_DEPENDENT_ERROR_INFORMATION configuration
| | |
| | | scpi_units_def, |
| | | SCPI_IDN1, SCPI_IDN2, SCPI_IDN3, SCPI_IDN4, |
| | | scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH, |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE, |
| | | NULL, 0); |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE); |
| | | |
| | | //printf("%.*s %s\r\n", 3, "asdadasdasdasdas", "b"); |
| | | printf("SCPI Interactive demo\r\n"); |
| | |
| | | scpi_units_def, |
| | | SCPI_IDN1, SCPI_IDN2, SCPI_IDN3, SCPI_IDN4, |
| | | scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH, |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE, |
| | | NULL, 0); |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE); |
| | | |
| | | #define TEST_SCPI_INPUT(cmd) result = SCPI_Input(&scpi_context, cmd, strlen(cmd)) |
| | | |
| | |
| | | scpi_units_def, |
| | | SCPI_IDN1, SCPI_IDN2, SCPI_IDN3, SCPI_IDN4, |
| | | scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH, |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE, |
| | | NULL, 0); |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE); |
| | | scpi_context.user_context = &user_data; |
| | | |
| | | user_data.io_listen = createServer(5025); |
| | |
| | | scpi_units_def, |
| | | SCPI_IDN1, SCPI_IDN2, SCPI_IDN3, SCPI_IDN4, |
| | | scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH, |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE, |
| | | NULL, 0); |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE); |
| | | |
| | | listenfd = createServer(5025); |
| | | |
| | |
| | | #define SCPIDEFINE_free(h, s, r) free((s)) |
| | | #else |
| | | #define SCPIDEFINE_DESCRIPTION_MAX_PARTS 3 |
| | | #define SCPIDEFINE_strndup(h, s, l) OUR_strndup((h), (s), (l)) |
| | | #define SCPIDEFINE_free(h, s, r) OUR_free((h), (s), (r)) |
| | | #define SCPIDEFINE_get_parts(h, s, l1, s2, l2) OUR_get_parts((h), (s), (l1), (s2), (l2)) |
| | | #define SCPIDEFINE_strndup(h, s, l) scpiheap_strndup((h), (s), (l)) |
| | | #define SCPIDEFINE_free(h, s, r) scpiheap_free((h), (s), (r)) |
| | | #define SCPIDEFINE_get_parts(h, s, l1, s2, l2) scpiheap_get_parts((h), (s), (l1), (s2), (l2)) |
| | | #endif |
| | | #else |
| | | #define SCPIDEFINE_DESCRIPTION_MAX_PARTS 1 |
| | | #define SCPIDEFINE_strdup(h, s, l) NULL |
| | | #define SCPIDEFINE_free(h, s, r) (void) |
| | | #define SCPIDEFINE_free(h, s, r) |
| | | #endif |
| | | |
| | | #ifdef __cplusplus |
| | |
| | | const scpi_unit_def_t * units, |
| | | const char * idn1, const char * idn2, const char * idn3, const char * idn4, |
| | | char * input_buffer, size_t input_buffer_length, |
| | | scpi_error_t * error_queue_data, int16_t error_queue_size, |
| | | char * error_info_heap, size_t error_info_heap_length); |
| | | scpi_error_t * error_queue_data, int16_t error_queue_size); |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | void SCPI_InitHeap(scpi_t * context, char * error_info_heap, size_t error_info_heap_length); |
| | | #endif |
| | | |
| | | scpi_bool_t SCPI_Input(scpi_t * context, const char * data, int len); |
| | | scpi_bool_t SCPI_Parse(scpi_t * context, char * data, int len); |
| | |
| | | |
| | | struct _scpi_error_t { |
| | | int16_t error_code; |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | char * device_dependent_info; |
| | | #endif |
| | | }; |
| | | typedef struct _scpi_error_t scpi_error_t; |
| | | |
| | |
| | | int_fast16_t input_count; |
| | | scpi_bool_t cmd_error; |
| | | scpi_fifo_t error_queue; |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | scpi_error_info_heap_t error_info_heap; |
| | | #endif |
| | | scpi_reg_val_t registers[SCPI_REG_COUNT]; |
| | | const scpi_unit_def_t * units; |
| | | void * user_context; |
| | |
| | | #include "scpi/error.h" |
| | | #include "fifo_private.h" |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | #define SCPI_ERROR_SETVAL(e, c, i) do { (e)->error_code = (c); (e)->device_dependent_info = (i); } while(0) |
| | | #else |
| | | #define SCPI_ERROR_SETVAL(e, c, i) do { (e)->error_code = (c); } while(0) |
| | | #endif |
| | | |
| | | /** |
| | | * Initialize error queue |
| | | * @param context - scpi context |
| | |
| | | */ |
| | | scpi_bool_t SCPI_ErrorPop(scpi_t * context, scpi_error_t * error) { |
| | | if (!error || !context) return FALSE; |
| | | error->error_code = 0; |
| | | error->device_dependent_info = NULL; |
| | | SCPI_ERROR_SETVAL(error, 0, NULL); |
| | | fifo_remove(&context->error_queue, error); |
| | | |
| | | SCPI_ErrorEmitEmpty(context); |
| | |
| | | |
| | | static scpi_bool_t SCPI_ErrorAddInternal(scpi_t * context, int16_t err, char * info) { |
| | | scpi_error_t error_value; |
| | | error_value.error_code = err; |
| | | error_value.device_dependent_info = info; |
| | | SCPI_ERROR_SETVAL(&error_value, err, info); |
| | | if (!fifo_add(&context->error_queue, &error_value)) { |
| | | fifo_remove_last(&context->error_queue, &error_value); |
| | | SCPIDEFINE_free(&context->error_info_heap, error_value.device_dependent_info, false); |
| | | error_value.error_code = SCPI_ERROR_QUEUE_OVERFLOW; |
| | | error_value.device_dependent_info = NULL; |
| | | SCPI_ERROR_SETVAL(&error_value, SCPI_ERROR_QUEUE_OVERFLOW, NULL); |
| | | fifo_add(&context->error_queue, &error_value); |
| | | return FALSE; |
| | | } |
| | |
| | | /** |
| | | * Initialize SCPI context structure |
| | | * @param context |
| | | * @param command_list |
| | | * @param buffer |
| | | * @param commands |
| | | * @param interface |
| | | * @param units |
| | | * @param idn1 |
| | | * @param idn2 |
| | | * @param idn3 |
| | | * @param idn4 |
| | | * @param input_buffer |
| | | * @param input_buffer_length |
| | | * @param error_queue_data |
| | | * @param error_queue_size |
| | | */ |
| | | void SCPI_Init(scpi_t * context, |
| | | const scpi_command_t * commands, |
| | |
| | | const scpi_unit_def_t * units, |
| | | const char * idn1, const char * idn2, const char * idn3, const char * idn4, |
| | | char * input_buffer, size_t input_buffer_length, |
| | | scpi_error_t * error_queue_data, int16_t error_queue_size, |
| | | char * error_info_heap, size_t error_info_heap_length) { |
| | | scpi_error_t * error_queue_data, int16_t error_queue_size) { |
| | | memset(context, 0, sizeof (*context)); |
| | | context->cmdlist = commands; |
| | | context->interface = interface; |
| | |
| | | context->buffer.data = input_buffer; |
| | | context->buffer.length = input_buffer_length; |
| | | context->buffer.position = 0; |
| | | context->error_info_heap.data = error_info_heap; |
| | | context->error_info_heap.wr = 0; |
| | | context->error_info_heap.size = error_info_heap_length; |
| | | context->error_info_heap.count = context->error_info_heap.size; |
| | | memset(context->error_info_heap.data, 0, context->error_info_heap.size); |
| | | SCPI_ErrorInit(context, error_queue_data, error_queue_size); |
| | | } |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | /** |
| | | * Initialize context's |
| | | * @param context |
| | | * @param data |
| | | * @param len |
| | | * @return |
| | | */ |
| | | void SCPI_InitHeap(scpi_t * context, |
| | | char * error_info_heap, size_t error_info_heap_length) { |
| | | scpiheap_init(&context->error_info_heap, error_info_heap, error_info_heap_length); |
| | | } |
| | | #endif |
| | | |
| | | /** |
| | | * Interface to the application. Adds data to system buffer and try to search |
| | | * command line termination. If the termination is found or if len=0, command |
| | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | |
| | | /** |
| | | * Initialize heap structure |
| | | * @param heap - pointer to manual allocated heap buffer |
| | | * @param error_info_heap - buffer for the heap |
| | | * @param error_info_heap_length - length of the heap |
| | | */ |
| | | void scpiheap_init(scpi_error_info_heap_t * heap, char * error_info_heap, size_t error_info_heap_length) |
| | | { |
| | | heap->data = error_info_heap; |
| | | heap->wr = 0; |
| | | heap->size = error_info_heap_length; |
| | | heap->count = heap->size; |
| | | memset(heap->data, 0, heap->size); |
| | | } |
| | | |
| | | /** |
| | | * Duplicate string if "strdup" ("malloc/free") not supported on system. |
| | | * Allocate space in heap if it possible |
| | | * |
| | |
| | | * @param s - current pointer of duplication string |
| | | * @return - pointer of duplicated string or NULL, if duplicate is not possible. |
| | | */ |
| | | char * OUR_strndup(scpi_error_info_heap_t * heap, const char *s, size_t n) { |
| | | if (!s || !heap) { |
| | | char * scpiheap_strndup(scpi_error_info_heap_t * heap, const char *s, size_t n) { |
| | | if (!s || !heap || !heap->size) { |
| | | return NULL; |
| | | } |
| | | |
| | |
| | | heap->wr += len; |
| | | heap->count -= len; |
| | | |
| | | // ensure '\0' a the end |
| | | if (heap->wr > 0) { |
| | | heap->data[heap->wr - 1] = '\0'; |
| | | } else { |
| | | heap->data[heap->size - 1] = '\0'; |
| | | } |
| | | return head; |
| | | } |
| | | |
| | |
| | | * @return s2 - pointer of second part of string, if string splited . |
| | | * @return len2 - lenght of second part of string. |
| | | */ |
| | | scpi_bool_t OUR_get_parts(scpi_error_info_heap_t * heap, const char * s, size_t * len1, const char ** s2, size_t * len2) { |
| | | scpi_bool_t scpiheap_get_parts(scpi_error_info_heap_t * heap, const char * s, size_t * len1, const char ** s2, size_t * len2) { |
| | | if (!heap || !s || !len1 || !s2 || !len2) { |
| | | return FALSE; |
| | | } |
| | |
| | | * @param s - pointer of duplicate string |
| | | * @param rollback - backward write pointer in heap |
| | | */ |
| | | void OUR_free(scpi_error_info_heap_t * heap, char * s, scpi_bool_t rollback) { |
| | | void scpiheap_free(scpi_error_info_heap_t * heap, char * s, scpi_bool_t rollback) { |
| | | |
| | | if (!s) return; |
| | | |
| | | char * data_add; |
| | | size_t len[2]; |
| | | |
| | | if (!OUR_get_parts(heap, s, &len[0], (const char **)&data_add, &len[1])) return; |
| | | if (!scpiheap_get_parts(heap, s, &len[0], (const char **)&data_add, &len[1])) return; |
| | | |
| | | if (data_add) { |
| | | len[1]++; |
| | |
| | | #endif |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | char * OUR_strndup(scpi_error_info_heap_t * heap, const char *s, size_t n) LOCAL; |
| | | void OUR_free(scpi_error_info_heap_t * heap, char *s, scpi_bool_t rollback) LOCAL; |
| | | scpi_bool_t OUR_get_parts(scpi_error_info_heap_t * heap, const char *s1, size_t * len1, const char ** s2, size_t * len2) LOCAL; |
| | | void scpiheap_init(scpi_error_info_heap_t * heap, char * error_info_heap, size_t error_info_heap_length); |
| | | char * scpiheap_strndup(scpi_error_info_heap_t * heap, const char *s, size_t n) LOCAL; |
| | | void scpiheap_free(scpi_error_info_heap_t * heap, char *s, scpi_bool_t rollback) LOCAL; |
| | | scpi_bool_t scpiheap_get_parts(scpi_error_info_heap_t * heap, const char *s1, size_t * len1, const char ** s2, size_t * len2) LOCAL; |
| | | #endif |
| | | |
| | | #ifndef min |
| | |
| | | #define SCPI_ERROR_QUEUE_SIZE 4 |
| | | static scpi_error_t scpi_error_queue_data[SCPI_ERROR_QUEUE_SIZE]; |
| | | |
| | | #define SCPI_ERROR_INFO_HEAP_SIZE 100 |
| | | static char error_info_heap[SCPI_ERROR_INFO_HEAP_SIZE]; |
| | | |
| | | static int init_suite(void) { |
| | | SCPI_Init(&scpi_context, |
| | | scpi_commands, |
| | |
| | | scpi_units_def, |
| | | "MA", "IN", NULL, "VER", |
| | | scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH, |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE, |
| | | NULL, 0); |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE); |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | SCPI_InitHeap(&scpi_context, |
| | | error_info_heap, SCPI_ERROR_INFO_HEAP_SIZE); |
| | | #endif |
| | | |
| | | return 0; |
| | | } |