diff --git a/m-core.h b/m-core.h index 8599a952..3aa4a2eb 100644 --- a/m-core.h +++ b/m-core.h @@ -1472,6 +1472,60 @@ /* IF FILE is supported */ #if M_USE_STDIO +/* Define internal wrappers around Annex K functions or classic functions for: + * - fopen + * - fscanf + * - strncpy + * + * There is no real usage outside of MSVS of Annex K, + * so the real standard compliant Annex K is not taken into account + * by this wrapper. + * + * If Microsoft Visual Studio C Library + * and the user wants to use the Annex K. + * ==> Use Annex K like functions to avoid warnings + * + * Only fscanf, fopen and strncpy produce warning, + * so we keep the wrapper as simple as possible by including only + * theses functions. + */ +#if defined(_MSC_VER) && defined(__STDC_WANT_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__ + +/* Wrapper around fopen_s */ +static inline FILE * +m_core_fopen(const char filename[], const char opt[]) +{ + FILE *f; + int err = fopen_s(&f, filename, opt); + if (err) return NULL; + return f; +} +/* Wrapper around strncpy_s */ +#define m_core_strncpy(s1, s2, size) strncpy_s(s1, size, s2, size) +/* Wrapper around fscanf_s */ +#define m_core_fscanf(...) fscanf_s(__VA_ARGS__) + +/* Macro to be used in m_core_fscanf for argument associated + * to the format %c, %s or %[ + * in order to specify the size of the argument */ +#define m_core_arg_size(arg, size) arg, (unsigned) size + +#else /* Use classic C functions */ + +/* Wrapper around fopen */ +#define m_core_fopen(...) fopen(__VA_ARGS__) +/* Wrapper around strncpy */ +#define m_core_strncpy(...) strncpy(__VA_ARGS__) +/* Wrapper around fscanf */ +#define m_core_fscanf(...) fscanf(__VA_ARGS__) + +/* Macro to be used in m_core_fscanf for argument associated + * to the format %c, %s or %[ + * in order to specify the size of the argument */ +#define m_core_arg_size(arg, size) arg + +#endif + /* Print a C variable if it is a standard type to stdout.*/ #define M_PRINT_ARG(x) printf(M_PRINTF_FORMAT(x), x) @@ -1509,13 +1563,20 @@ m_core_fscan_bool (bool *ptr, FILE *f) return (c == '0' || c == '1'); } +static inline bool +m_core_fscan_char (char *ptr, FILE *f) +{ + int c = fgetc(f); + *ptr = (char) c; + return c != EOF; +} + #define M_FSCAN_DEFAULT_TYPE_DEF(name, type, format) \ static inline bool \ name (type *ptr, FILE *f) \ { \ - return fscanf(f, format, ptr) == 1; \ + return m_core_fscanf(f, format, ptr) == 1; \ } -M_FSCAN_DEFAULT_TYPE_DEF(m_core_fscan_char, char, "%c") M_FSCAN_DEFAULT_TYPE_DEF(m_core_fscan_schar, signed char, "%hhd") M_FSCAN_DEFAULT_TYPE_DEF(m_core_fscan_uchar, unsigned char, "%hhu") M_FSCAN_DEFAULT_TYPE_DEF(m_core_fscan_sshort, signed short, "%hd") diff --git a/m-serial-json.h b/m-serial-json.h index ace3219c..5e192eca 100644 --- a/m-serial-json.h +++ b/m-serial-json.h @@ -324,7 +324,7 @@ static inline m_serial_return_code_t m_serial_json_read_integer(m_serial_read_t serial, long long *i, const size_t size_of_type){ (void) size_of_type; // Ignored FILE *f = (FILE*) serial->data[0].p; - return fscanf(f, " %lld", i) == 1 ? M_SERIAL_OK_DONE : m_core_serial_fail(); + return m_core_fscanf(f, " %lld", i) == 1 ? M_SERIAL_OK_DONE : m_core_serial_fail(); } /* Read from the stream 'serial' a float that can be represented with 'size_of_type' bytes. @@ -334,7 +334,7 @@ static inline m_serial_return_code_t m_serial_json_read_float(m_serial_read_t serial, long double *r, const size_t size_of_type){ (void) size_of_type; // Ignored FILE *f = (FILE*) serial->data[0].p; - return fscanf(f, " %Lf", r) == 1 ? M_SERIAL_OK_DONE : m_core_serial_fail(); + return m_core_fscanf(f, " %Lf", r) == 1 ? M_SERIAL_OK_DONE : m_core_serial_fail(); } /* Read from the stream 'serial' a string. @@ -343,7 +343,7 @@ m_serial_json_read_float(m_serial_read_t serial, long double *r, const size_t si static inline m_serial_return_code_t m_serial_json_read_string(m_serial_read_t serial, struct string_s *s){ FILE *f = (FILE*) serial->data[0].p; - fscanf(f, " "); // Skip any leading spaces. + m_core_fscanf(f, " "); // Skip any leading spaces. return string_in_str(s, f) ? M_SERIAL_OK_DONE : m_core_serial_fail(); } @@ -360,7 +360,7 @@ m_serial_json_read_array_start(m_serial_local_t local, m_serial_read_t serial, s (void) local; // argument not used FILE *f = (FILE*) serial->data[0].p; int final1 = -1, final2 = -1; - fscanf(f, " [%n ]%n", &final1, &final2); + m_core_fscanf(f, " [%n ]%n", &final1, &final2); *num = 0; // don't know the size of the array. // Test how much the parsing succeed. if (final1 < 0) m_core_serial_fail(); @@ -377,7 +377,7 @@ m_serial_json_read_array_next(m_serial_local_t local, m_serial_read_t serial) (void) local; // argument not used FILE *f = (FILE*) serial->data[0].p; char c = 0; - fscanf(f, " %c", &c); + m_core_fscanf(f, " %c", m_core_arg_size(&c, 1) ); return c == ',' ? M_SERIAL_OK_CONTINUE : c == ']' ? M_SERIAL_OK_DONE : m_core_serial_fail(); } @@ -394,7 +394,7 @@ m_serial_json_read_map_start(m_serial_local_t local, m_serial_read_t serial, siz (void) local; // argument not used FILE *f = (FILE*) serial->data[0].p; int final1 = -1, final2 = -1; - fscanf(f, " {%n }%n", &final1, &final2); + m_core_fscanf(f, " {%n }%n", &final1, &final2); *num = 0; // don't know the size of the map. // Test how much the parsing succeed. if (final1 < 0) m_core_serial_fail(); @@ -410,7 +410,7 @@ m_serial_json_read_map_value(m_serial_local_t local, m_serial_read_t serial) (void) local; // argument not used FILE *f = (FILE*) serial->data[0].p; int final = -1; - fscanf(f, " :%n", &final); + m_core_fscanf(f, " :%n", &final); return final > 0 ? M_SERIAL_OK_CONTINUE : m_core_serial_fail(); } @@ -424,7 +424,7 @@ m_serial_json_read_map_next(m_serial_local_t local, m_serial_read_t serial) (void) local; // argument not used FILE *f = (FILE*) serial->data[0].p; char c = 0; - fscanf(f, " %c", &c); + m_core_fscanf(f, " %c", m_core_arg_size(&c, 1) ); return c == ',' ? M_SERIAL_OK_CONTINUE : c == '}' ? M_SERIAL_OK_DONE : m_core_serial_fail(); } @@ -437,7 +437,7 @@ m_serial_json_read_tuple_start(m_serial_local_t local, m_serial_read_t serial) (void) local; // argument not used FILE *f = (FILE*) serial->data[0].p; int final = -1; - fscanf(f, " {%n", &final); + m_core_fscanf(f, " {%n", &final); return final > 0 ? M_SERIAL_OK_CONTINUE : m_core_serial_fail(); } @@ -464,8 +464,9 @@ m_serial_json_read_tuple_id(m_serial_local_t local, m_serial_read_t serial, cons } /* Read the field in the JSON */ c = -1; - char field[M_MAX_IDENTIFIER_LENGTH+1]; // TODO: fix error detection below. - fscanf(f, " \"%" M_APPLY(M_AS_STR, M_MAX_IDENTIFIER_LENGTH) "[^ \t\n\"]\":%n", field, &c); + char field[M_MAX_IDENTIFIER_LENGTH+1]; + m_core_fscanf(f, " \"%" M_APPLY(M_AS_STR, M_MAX_IDENTIFIER_LENGTH) "[^ \t\n\"]\":%n", + m_core_arg_size(field, M_MAX_IDENTIFIER_LENGTH+1), &c); if (c <= 0) return m_core_serial_fail(); /* Search for field in field_name */ @@ -491,23 +492,25 @@ m_serial_json_read_variant_start(m_serial_local_t local, m_serial_read_t serial, FILE *f = (FILE*) serial->data[0].p; int final1 = -1, final2 = -1; - fscanf(f, " {%n }%n", &final1, &final2); + m_core_fscanf(f, " {%n }%n", &final1, &final2); // Test how much the parsing succeed. if (final1 <= 0) return m_core_serial_fail(); if (final2 > 0) return M_SERIAL_OK_DONE; /* Read the field in the JSON */ char field[M_MAX_IDENTIFIER_LENGTH+1]; - fscanf(f, " \"%" M_APPLY(M_AS_STR, M_MAX_IDENTIFIER_LENGTH) "[^ \t\n\"]\":%n", field, &final2); + m_core_fscanf(f, " \"%" M_APPLY(M_AS_STR, M_MAX_IDENTIFIER_LENGTH) "[^ \t\n\"]\":%n", + m_core_arg_size(field, M_MAX_IDENTIFIER_LENGTH+1), &final2); if (final2 <= 0) return m_core_serial_fail(); - /* Search for field in field_name */ + /* Linear Search for field in field_name */ for(int n = 0; n < max; n++) { if (strcmp(field, field_name[n]) == 0) { *id = n; return M_SERIAL_OK_CONTINUE; } } + // Field not found return m_core_serial_fail(); } @@ -520,7 +523,7 @@ m_serial_json_read_variant_end(m_serial_local_t local, m_serial_read_t serial) (void) local; // argument not used FILE *f = (FILE*) serial->data[0].p; int final = -1; - fscanf(f, " }%n", &final); + m_core_fscanf(f, " }%n", &final); return final > 0 ? M_SERIAL_OK_DONE : m_core_serial_fail(); } diff --git a/m-string.h b/m-string.h index 2bf01fa6..2c9a23be 100644 --- a/m-string.h +++ b/m-string.h @@ -918,7 +918,7 @@ string_fget_word (string_t v, const char separator[], FILE *f) an opportunity for stack overflow */ while (snprintf(buffer, sizeof buffer -1, " %%%zu[^%s]%%c", (size_t) alloc-1-size, separator) > 0 /* We may read one or two argument(s) */ - && fscanf(f, buffer, &ptr[size], &c) >= 1) { + && m_core_fscanf(f, buffer, m_core_arg_size(&ptr[size], alloc-size), &c) >= 1) { retcode = true; size += strlen(&ptr[size]); /* If we read only one argument @@ -1824,7 +1824,7 @@ namespace m_string { M_C(name, _set_str)(M_C(name,_t) s, const char str[]) \ { \ BOUNDED_STRINGI_CONTRACT(s, max_size); \ - strncpy(s->s, str, max_size); \ + m_core_strncpy(s->s, str, max_size); \ BOUNDED_STRINGI_CONTRACT(s, max_size); \ } \ \ @@ -1834,7 +1834,7 @@ namespace m_string { BOUNDED_STRINGI_CONTRACT(s, max_size); \ assert(str != NULL); \ size_t len = M_MIN(max_size, n); \ - strncpy(s->s, str, len); \ + m_core_strncpy(s->s, str, len); \ s->s[len] = 0; \ BOUNDED_STRINGI_CONTRACT(s, max_size); \ } \ @@ -2045,7 +2045,7 @@ namespace m_string { string_t v2; \ string_init(v2); \ bool ret = string_in_str(v2, f); \ - strncpy(v->s, string_get_cstr(v2), max_size); \ + m_core_strncpy(v->s, string_get_cstr(v2), max_size); \ string_clear(v2); \ return ret; \ } \ @@ -2058,7 +2058,7 @@ namespace m_string { string_t v2; \ string_init(v2); \ bool ret = string_parse_str(v2, str, endptr); \ - strncpy(v->s, string_get_cstr(v2), max_size); \ + m_core_strncpy(v->s, string_get_cstr(v2), max_size); \ string_clear(v2); \ return ret; \ } \ @@ -2080,7 +2080,7 @@ namespace m_string { /* TODO: Not optimum */ \ string_init(tmp); \ m_serial_return_code_t r = serial->m_interface->read_string(serial, tmp); \ - strncpy(v->s, string_get_cstr(tmp), max_size); \ + m_core_strncpy(v->s, string_get_cstr(tmp), max_size); \ string_clear(tmp); \ BOUNDED_STRINGI_CONTRACT(v, max_size); \ return r; \ @@ -2113,7 +2113,7 @@ namespace m_string { inline m_bounded_string(const char lstr[]) { memset(this->s, 0, N); - strncpy(this->s, lstr, N-1); + m_core_strncpy(this->s, lstr, N-1); } }; }