| | |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | #include <malloc.h> |
| | | #define SCPIDEFINE_strdup(h,s) strdup((s)) |
| | | #define SCPIDEFINE_free(h,s) free((s)) |
| | | #define SCPIDEFINE_DESCRIPTION_MAX_PARTS 2 |
| | | #define SCPIDEFINE_strdup(h, s) strdup((s)) |
| | | #define SCPIDEFINE_free(h, s, r) free((s)) |
| | | #else |
| | | #define SCPIDEFINE_strdup(h,s) OUR_strdup((h), (s)) |
| | | #define SCPIDEFINE_free(h,s) OUR_free((h), (s)) |
| | | #define SCPIDEFINE_get_1st_part(s,l) OUR_get_1st_part((s),(l)) |
| | | #define SCPIDEFINE_get_2st_part(s,l) OUR_get_2nd_part((s),(l)) |
| | | #define SCPIDEFINE_DESCRIPTION_MAX_PARTS 3 |
| | | #define SCPIDEFINE_strdup(h, s) OUR_strdup((h), (s)) |
| | | #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)) |
| | | #endif |
| | | #else |
| | | #define SCPIDEFINE_strdup(h,s) (void)(s) |
| | | #define SCPIDEFINE_free(h,s) (void)(s) |
| | | #define SCPIDEFINE_DESCRIPTION_MAX_PARTS 1 |
| | | #define SCPIDEFINE_strdup(h, s) NULL |
| | | #define SCPIDEFINE_free(h, s, r) (void) |
| | | #endif |
| | | |
| | | #ifdef __cplusplus |
| | |
| | | */ |
| | | #define SCPI_STD_VERSION_REVISION "1999.0" |
| | | |
| | | /* 21.8 :ERRor Subsystem |
| | | * The maximum string length of <Error/event_description> plus <Device-dependent_info> is 255 characters. |
| | | */ |
| | | #define SCPI_STD_ERROR_DESC_CHARS_LIMIT 255 |
| | | |
| | | #ifdef __cplusplus |
| | | } |
| | | #endif |
| | |
| | | |
| | | struct _scpi_error_info_heap_t { |
| | | int16_t wr; |
| | | int16_t rd; |
| | | //int16_t rd; |
| | | int16_t count; |
| | | int16_t size; |
| | | char * data; |
| | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | scpi_error_t error; |
| | | while(fifo_remove(&context->error_queue, &error)){ |
| | | SCPIDEFINE_free(&context->error_info_heap, error.device_dependent_info); |
| | | SCPIDEFINE_free(&context->error_info_heap, error.device_dependent_info, false); |
| | | } |
| | | #endif |
| | | fifo_clear(&context->error_queue); |
| | |
| | | |
| | | static scpi_bool_t SCPI_ErrorAddInternal(scpi_t * context, int16_t err, char * info) { |
| | | if (!fifo_add(&context->error_queue, err, info)) { |
| | | scpi_error_t * error; |
| | | fifo_remove_last(&context->error_queue, error); |
| | | SCPIDEFINE_free(&context->error_info_heap, error->device_dependent_info); |
| | | fifo_remove_last(&context->error_queue, NULL); |
| | | fifo_add(&context->error_queue, SCPI_ERROR_QUEUE_OVERFLOW, NULL); |
| | | return FALSE; |
| | | } |
| | |
| | | SCPI_ErrorEmit(context, err); |
| | | if (queue_overflow) { |
| | | SCPI_ErrorEmit(context, SCPI_ERROR_QUEUE_OVERFLOW); |
| | | SCPIDEFINE_free(&context->error_info_heap, info_ptr, true); |
| | | } |
| | | |
| | | if (context) { |
| | |
| | | * @return |
| | | */ |
| | | scpi_result_t SCPI_SystemErrorNextQ(scpi_t * context) { |
| | | scpi_error_t error; |
| | | SCPI_ResultInt32(context,context->error_info_heap.count); |
| | | |
| | | scpi_error_t error; |
| | | SCPI_ErrorPopEx(context, &error); |
| | | SCPI_ResultError(context, &error); |
| | | |
| | | SCPI_ResultInt32(context,context->error_info_heap.count); |
| | | return SCPI_RES_OK; |
| | | |
| | | //int16_t err = SCPI_ErrorPop(context); |
| | | //SCPI_ResultInt32(context, error.error_code); |
| | | //SCPI_ResultText(context, SCPI_ErrorTranslate(error.error_code)); |
| | | //return SCPI_RES_OK; |
| | | |
| | | } |
| | | |
| | | /** |
| | |
| | | context->buffer.length = input_buffer_length; |
| | | context->buffer.position = 0; |
| | | context->error_info_heap.data = error_info_heap; |
| | | context->error_info_heap.position = 0; |
| | | context->error_info_heap.length = error_info_heap_length; |
| | | 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); |
| | | } |
| | | |
| | |
| | | return result; |
| | | } |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | #if USE_MEMORY_ALLOCATION_FREE |
| | | #define MAX_BUFF_SIZE 2 |
| | | #else |
| | | #define MAX_BUFF_SIZE 3 |
| | | #endif |
| | | #else |
| | | #define MAX_BUFF_SIZE 1 |
| | | #endif |
| | | |
| | | static size_t startoutputlimit = 0; |
| | | |
| | | /** |
| | | * Write string withn " to the result |
| | | * @param context |
| | | * @param data |
| | | * @return |
| | | */ |
| | | static size_t outputlimit_0=0; |
| | | size_t SCPI_ResultError(scpi_t * context, scpi_error_t * error) { |
| | | size_t result = 0; |
| | | size_t outputlimit = startoutputlimit++; |
| | | size_t outputlimit = outputlimit_0++; //SCPI_STD_ERROR_DESC_CHARS_LIMIT; |
| | | size_t step = 0; |
| | | const char * quote; |
| | | |
| | | char * data[MAX_BUFF_SIZE]; |
| | | size_t len[MAX_BUFF_SIZE]; |
| | | char * data[SCPIDEFINE_DESCRIPTION_MAX_PARTS]; |
| | | size_t len[SCPIDEFINE_DESCRIPTION_MAX_PARTS]; |
| | | |
| | | data[0] = SCPI_ErrorTranslate(error->error_code); |
| | | len[0] = strlen(data[0]); |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | data[1] = error->device_dependent_info; |
| | | #if USE_MEMORY_ALLOCATION_FREE |
| | | data[1] = error->device_dependent_info; |
| | | len[1] = error->device_dependent_info ? strlen(data[1]) : 0; |
| | | #else |
| | | data[1] = SCPIDEFINE_get_1st_part(error->device_dependent_info,&len[1]); |
| | | data[2] = SCPIDEFINE_get_1st_part(data[1],&len[2]); |
| | | SCPIDEFINE_get_parts(&context->error_info_heap, data[1], &len[1], &data[2], &len[2]); |
| | | #endif |
| | | #endif |
| | | |
| | |
| | | result += writeDelimiter(context); |
| | | result += writeData(context, "\"", 1); |
| | | |
| | | for(size_t i = 0; data[i] && outputlimit && (i < MAX_BUFF_SIZE); i++){ |
| | | for(size_t i = 0; data[i] && outputlimit && (i < SCPIDEFINE_DESCRIPTION_MAX_PARTS); i++){ |
| | | if(i==1){ |
| | | result += writeSemicolon(context); |
| | | outputlimit -= 1; |
| | |
| | | result += writeData(context, "\"", 1); |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | #if USE_MEMORY_ALLOCATION_FREE |
| | | SCPIDEFINE_free(error->device_dependent_info); |
| | | #else |
| | | #endif |
| | | SCPIDEFINE_free(&context->error_info_heap, error->device_dependent_info, false); |
| | | #endif |
| | | |
| | | return result; |
| | | } |
| | | #undef MAX_BUFF_SIZE |
| | | |
| | | /** |
| | | * Write arbitrary block header with length |
| | |
| | | #endif |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | /** |
| | | * Duplicate string if "strdup" ("malloc/free") not supported on system. |
| | | * Allocate space in heap if it possible |
| | | * |
| | | * @param heap - pointer to manual allocated heap buffer |
| | | * @param s - current pointer of duplication string |
| | | * @return - pointer of duplicated string or NULL, if duplicate is not possible. |
| | | */ |
| | | char * OUR_strdup(scpi_error_info_heap_t * heap, const char *s) { |
| | | if(!heap || !s) { |
| | | if(!s || !heap) { |
| | | return NULL; |
| | | } |
| | | if(heap->data[heap->wr]!='\0'){ |
| | |
| | | if(len > heap->count){ |
| | | return NULL; |
| | | } |
| | | size_t f_part=(&heap->data[heap->wr]-heap->data) |
| | | char * ptrs = s; |
| | | char * head = &heap->data[heap->wr]; |
| | | size_t rem = heap->size - (&heap->data[heap->wr]-heap->data); |
| | | size_t sstp = 0; |
| | | |
| | | if(len >= rem){ |
| | | memcpy(&heap->data[heap->wr],s,rem); |
| | | len = len - rem; |
| | | ptrs += rem; |
| | | heap->wr = 0; |
| | | heap->count -= rem; |
| | | } |
| | | |
| | | memcpy(&heap->data[heap->wr],ptrs,len); |
| | | heap->wr += len; |
| | | heap->count -= len; |
| | | |
| | | return head; |
| | | } |
| | | |
| | | /** |
| | | * Return pointers and lengths two parts of string in the circular buffer from heap |
| | | * |
| | | * @param heap - pointer to manual allocated heap buffer |
| | | * @param s - pointer of duplicate string. |
| | | * @return len1 - lenght of first part of string. |
| | | * @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) { |
| | | if(!heap || !s || !len1 || !s2 || !len2) { |
| | | return FALSE; |
| | | } |
| | | |
| | | if(*s == '\0') { |
| | | return FALSE; |
| | | } |
| | | |
| | | *len1 = 0; |
| | | size_t rem = heap->size - (s - heap->data); |
| | | *len1 = strnlen(s, rem); |
| | | |
| | | if(&s[*len1-1] == &heap->data[heap->size-1]){ |
| | | *s2 = heap->data; |
| | | *len2 = strnlen(*s2, heap->size); |
| | | }else{ |
| | | *s2 = NULL; |
| | | *len2 = 0; |
| | | } |
| | | return TRUE; |
| | | } |
| | | |
| | | /** |
| | | * Frees space in heap, if "malloc/free" not supported on system, or nothing. |
| | | * |
| | | * @param heap - pointer to manual allocated heap buffer |
| | | * @param s - pointer of duplicate string |
| | | * @param rollback - backward write pointer in heap |
| | | */ |
| | | void OUR_free(scpi_error_info_heap_t * heap, const char * s, scpi_bool_t rollback) { |
| | | |
| | | if(!s) return; |
| | | |
| | | char * data_add; |
| | | size_t len[2]; |
| | | |
| | | if( !OUR_get_parts( heap, s, &len[0], &data_add, &len[1] ) ) return; |
| | | |
| | | |
| | | return NULL; |
| | | if(data_add) { |
| | | len[1]++; |
| | | memset(data_add,0,len[1]); |
| | | heap->count += len[1]; |
| | | } else { |
| | | len[0]++; |
| | | } |
| | | memset(s,0,len[0]); |
| | | heap->count += len[0]; |
| | | if(rollback){ |
| | | heap->wr-=len[0]; |
| | | heap->wr-=len[1]; |
| | | if(heap->wr < 0)heap->wr += heap->size; |
| | | } |
| | | } |
| | | void OUR_free(scpi_error_info_heap_t * heap, const char *s) { |
| | | |
| | | } |
| | | char * OUR_get_1st_part(const char *s, size_t * len) { |
| | | return NULL; |
| | | } |
| | | char * OUR_get_2nd_part(const char *s, size_t * len) { |
| | | return NULL; |
| | | } |
| | | |
| | | #endif |
| | | |
| | | // Floating point to string conversion routines |
| | |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE |
| | | char * OUR_strdup(scpi_error_info_heap_t * heap, const char *s) LOCAL; |
| | | void OUR_free(scpi_error_info_heap_t * heap, const char *s) LOCAL; |
| | | char * OUR_get_1st_part(const char *s, size_t * len) LOCAL; |
| | | char * OUR_get_2nd_part(const char *s, size_t * len) LOCAL; |
| | | void OUR_free(scpi_error_info_heap_t * heap, const 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; |
| | | #endif |
| | | |
| | | #ifndef min |