diff --git a/Android.mk b/Android.mk index f50d917..9a52f5f 100644 --- a/Android.mk +++ b/Android.mk @@ -43,6 +43,7 @@ VKRUNNER_SRC_FILES := vkrunner/vr-allocate-store.c \ vkrunner/vr-script.c \ vkrunner/vr-source.c \ vkrunner/vr-stream.c \ + vkrunner/vr-strtof.c \ vkrunner/vr-subprocess.c \ vkrunner/vr-temp-file.c \ vkrunner/vr-test.c \ diff --git a/vkrunner/CMakeLists.txt b/vkrunner/CMakeLists.txt index b491159..4aefe83 100644 --- a/vkrunner/CMakeLists.txt +++ b/vkrunner/CMakeLists.txt @@ -49,6 +49,8 @@ set(VKRUNNER_SOURCE_FILES vr-source.c vr-stream.c vr-stream.h + vr-strtof.c + vr-strtof.h vr-temp-file.c vr-temp-file.h vr-util.c diff --git a/vkrunner/vr-config.h b/vkrunner/vr-config.h index 8dc92ec..6cdaea1 100644 --- a/vkrunner/vr-config.h +++ b/vkrunner/vr-config.h @@ -29,6 +29,7 @@ #include #include "vr-result.h" #include "vr-callback.h" +#include "vr-strtof.h" struct vr_config { bool show_disassembly; @@ -36,6 +37,8 @@ struct vr_config { vr_callback_error error_cb; vr_callback_inspect inspect_cb; void *user_data; + + struct vr_strtof_data strtof_data; }; #endif /* VR_CONFIG_H */ diff --git a/vkrunner/vr-executor.c b/vkrunner/vr-executor.c index 2aa82bb..7ca5a89 100644 --- a/vkrunner/vr-executor.c +++ b/vkrunner/vr-executor.c @@ -169,6 +169,8 @@ vr_executor_new(void) { struct vr_executor *executor = vr_calloc(sizeof *executor); + vr_strtof_init(&executor->config.strtof_data); + return executor; } @@ -318,5 +320,7 @@ vr_executor_free(struct vr_executor *executor) { free_context(executor); + vr_strtof_destroy(&executor->config.strtof_data); + vr_free(executor); } diff --git a/vkrunner/vr-hex.c b/vkrunner/vr-hex.c index 4386c05..1c5b061 100644 --- a/vkrunner/vr-hex.c +++ b/vkrunner/vr-hex.c @@ -37,7 +37,9 @@ * pattern to generate a float value. */ float -vr_hex_strtof(const char *nptr, char **endptr) +vr_hex_strtof(const struct vr_strtof_data *data, + const char *nptr, + char **endptr) { /* skip spaces and tabs */ while (*nptr == ' ' || *nptr == '\t') @@ -52,7 +54,7 @@ vr_hex_strtof(const char *nptr, char **endptr) x.u = strtoul(nptr, endptr, 16); return x.f; } else { - return strtod(nptr, endptr); + return vr_strtod(data, nptr, endptr); } } @@ -61,7 +63,9 @@ vr_hex_strtof(const char *nptr, char **endptr) * pattern to generate a double value. */ double -vr_hex_strtod(const char *nptr, char **endptr) +vr_hex_strtod(const struct vr_strtof_data *data, + const char *nptr, + char **endptr) { /* skip spaces and tabs */ while (*nptr == ' ' || *nptr == '\t') @@ -76,7 +80,7 @@ vr_hex_strtod(const char *nptr, char **endptr) x.u64 = strtoull(nptr, endptr, 16); return x.d; } else { - return strtod(nptr, endptr); + return vr_strtod(data, nptr, endptr); } } @@ -85,7 +89,9 @@ vr_hex_strtod(const char *nptr, char **endptr) * generate a signed int value. */ int -vr_hex_strtol(const char *nptr, char **endptr) +vr_hex_strtol(const struct vr_strtof_data *data, + const char *nptr, + char **endptr) { /* skip spaces and tabs */ while (*nptr == ' ' || *nptr == '\t') @@ -109,7 +115,9 @@ vr_hex_strtol(const char *nptr, char **endptr) * hex bit pattern to generate a half float value. */ uint16_t -vr_hex_strtohf(const char *nptr, char **endptr) +vr_hex_strtohf(const struct vr_strtof_data *data, + const char *nptr, + char **endptr) { /* skip spaces and tabs */ while (*nptr == ' ' || *nptr == '\t') @@ -124,6 +132,6 @@ vr_hex_strtohf(const char *nptr, char **endptr) return u; } } else { - return vr_half_float_from_float(strtod(nptr, endptr)); + return vr_half_float_from_float(vr_strtod(data, nptr, endptr)); } } diff --git a/vkrunner/vr-hex.h b/vkrunner/vr-hex.h index a28ba41..a710ec7 100644 --- a/vkrunner/vr-hex.h +++ b/vkrunner/vr-hex.h @@ -25,17 +25,26 @@ #define VR_HEX_H #include +#include "vr-strtof.h" float -vr_hex_strtof(const char *nptr, char **endptr); +vr_hex_strtof(const struct vr_strtof_data *data, + const char *nptr, + char **endptr); double -vr_hex_strtod(const char *nptr, char **endptr); +vr_hex_strtod(const struct vr_strtof_data *data, + const char *nptr, + char **endptr); int -vr_hex_strtol(const char *nptr, char **endptr); +vr_hex_strtol(const struct vr_strtof_data *data, + const char *nptr, + char **endptr); uint16_t -vr_hex_strtohf(const char *nptr, char **endptr); +vr_hex_strtohf(const struct vr_strtof_data *data, + const char *nptr, + char **endptr); #endif /* VR_HEX_H */ diff --git a/vkrunner/vr-script.c b/vkrunner/vr-script.c index 25a34be..bfd9ed4 100644 --- a/vkrunner/vr-script.c +++ b/vkrunner/vr-script.c @@ -216,7 +216,8 @@ is_end(const char *p) } static bool -parse_floats(const char **p, +parse_floats(struct load_state *data, + const char **p, float *out, int n_floats, const char *sep) @@ -228,7 +229,7 @@ parse_floats(const char **p, (*p)++; errno = 0; - *(out++) = strtof(*p, &tail); + *(out++) = vr_strtof(&data->config->strtof_data, *p, &tail); if (errno != 0 || tail == *p) return false; *p = tail; @@ -245,7 +246,8 @@ parse_floats(const char **p, } static bool -parse_doubles(const char **p, +parse_doubles(struct load_state *data, + const char **p, double *out, int n_doubles, const char *sep) @@ -257,7 +259,7 @@ parse_doubles(const char **p, (*p)++; errno = 0; - *(out++) = strtod(*p, &tail); + *(out++) = vr_strtod(&data->config->strtof_data, *p, &tail); if (errno != 0 || tail == *p) return false; *p = tail; @@ -641,7 +643,8 @@ parse_value_type(const char **p, } static bool -parse_value(const char **p, +parse_value(struct load_state *data, + const char **p, enum vr_box_type type, void *value) { @@ -708,14 +711,16 @@ parse_value(const char **p, return false; break; case VR_BOX_BASE_TYPE_FLOAT: - if (!parse_floats(p, + if (!parse_floats(data, + p, (float *) value + col * stride, info->rows, NULL)) return false; break; case VR_BOX_BASE_TYPE_DOUBLE: - if (!parse_doubles(p, + if (!parse_doubles(data, + p, (double *) value + col * stride, info->rows, NULL)) @@ -728,7 +733,8 @@ parse_value(const char **p, } static bool -parse_box_values(const char **p, +parse_box_values(struct load_state *data, + const char **p, enum vr_box_type type, size_t alignment, size_t *size_out, @@ -742,7 +748,8 @@ parse_box_values(const char **p, vr_align(buffer.length, alignment) + type_size); - if (!parse_value(p, + if (!parse_value(data, + p, type, buffer.data + buffer.length - type_size)) { vr_buffer_destroy(&buffer); @@ -757,14 +764,20 @@ parse_box_values(const char **p, } static bool -parse_buffer_subdata(const char **p, +parse_buffer_subdata(struct load_state *data, + const char **p, enum vr_box_type type, size_t *size_out, void **buffer_out) { size_t alignment = vr_box_type_base_alignment(type); - return parse_box_values(p, type, alignment, size_out, buffer_out); + return parse_box_values(data, + p, + type, + alignment, + size_out, + buffer_out); } static bool @@ -813,7 +826,8 @@ parse_tolerance(struct load_state *data, int n_tolerance, bool parse_percent) { - if (parse_doubles(&p, + if (parse_doubles(data, + &p, data->tolerance.value, n_tolerance, parse_percent ? "%" : NULL)) { @@ -994,7 +1008,7 @@ process_draw_rect_command(struct load_state *data, vr_pipeline_key_destroy(&key); - if (!parse_floats(&p, &command->draw_rect.x, 4, NULL) || + if (!parse_floats(data, &p, &command->draw_rect.x, 4, NULL) || !is_end(p)) return false; @@ -1013,15 +1027,15 @@ process_draw_rect_command(struct load_state *data, } static bool -process_probe_command(const char *p, - struct vr_script_command *command, - const struct vr_tolerance *tolerance) +process_probe_command(struct load_state *data, + const char *p, + struct vr_script_command *command) { bool relative = false; enum { POINT, RECT, ALL } region_type = POINT; int n_components; - command->probe_rect.tolerance = *tolerance; + command->probe_rect.tolerance = data->tolerance; if (looking_at(&p, "relative ")) relative = true; @@ -1047,7 +1061,8 @@ process_probe_command(const char *p, if (region_type == ALL) { if (relative) return false; - if (!parse_doubles(&p, + if (!parse_doubles(data, + &p, command->probe_rect.color, n_components, NULL)) @@ -1070,7 +1085,7 @@ process_probe_command(const char *p, if (region_type == POINT) { if (relative) { float rel_pos[2]; - if (!parse_floats(&p, rel_pos, 2, ",")) + if (!parse_floats(data, &p, rel_pos, 2, ",")) return false; command->probe_rect.x = rel_pos[0] * VR_WINDOW_WIDTH; command->probe_rect.y = rel_pos[1] * VR_WINDOW_HEIGHT; @@ -1084,7 +1099,7 @@ process_probe_command(const char *p, if (relative) { float rel_pos[4]; - if (!parse_floats(&p, rel_pos, 4, ",")) + if (!parse_floats(data, &p, rel_pos, 4, ",")) return false; command->probe_rect.x = rel_pos[0] * VR_WINDOW_WIDTH; command->probe_rect.y = rel_pos[1] * VR_WINDOW_HEIGHT; @@ -1107,7 +1122,11 @@ process_probe_command(const char *p, return false; p++; - if (!parse_doubles(&p, command->probe_rect.color, n_components, ",")) + if (!parse_doubles(data, + &p, + command->probe_rect.color, + n_components, + ",")) return false; while (isspace(*p)) @@ -1123,9 +1142,9 @@ process_probe_command(const char *p, } static bool -process_probe_ssbo_command(const char *p, - struct vr_script_command *command, - const struct vr_tolerance *tolerance) +process_probe_ssbo_command(struct load_state *data, + const char *p, + struct vr_script_command *command) { if (!looking_at(&p, "probe ssbo ")) return false; @@ -1174,7 +1193,8 @@ process_probe_ssbo_command(const char *p, size_t value_size; - if (!parse_box_values(&p, + if (!parse_box_values(data, + &p, command->probe_ssbo.type, 1, /* alignment */ &value_size, @@ -1189,7 +1209,7 @@ process_probe_ssbo_command(const char *p, size_t type_size = vr_box_type_size(command->probe_ssbo.type); command->probe_ssbo.n_values = value_size / type_size; command->op = VR_SCRIPT_OP_PROBE_SSBO; - command->probe_ssbo.tolerance = *tolerance; + command->probe_ssbo.tolerance = data->tolerance; return true; } @@ -1439,7 +1459,7 @@ process_float_property(struct load_state *data, while (isspace(*p)) p++; - if (!parse_floats(&p, &value->f, 1, NULL) || !is_end(p)) { + if (!parse_floats(data, &p, &value->f, 1, NULL) || !is_end(p)) { vr_error_message(data->config, "%s:%i: Invalid float value", data->filename, @@ -1536,7 +1556,8 @@ process_set_buffer_subdata(struct load_state *data, goto error; if (!parse_size_t(&p, &command->set_buffer_subdata.offset)) goto error; - if (!parse_buffer_subdata(&p, + if (!parse_buffer_subdata(data, + &p, value_type, &command->set_buffer_subdata.size, &command->set_buffer_subdata.data)) @@ -1637,7 +1658,7 @@ process_test_line(struct load_state *data) } if (looking_at(&p, "clear color ")) { - if (!parse_floats(&p, data->clear_color, 4, NULL)) + if (!parse_floats(data, &p, data->clear_color, 4, NULL)) goto error; if (!is_end(p)) goto error; @@ -1645,7 +1666,7 @@ process_test_line(struct load_state *data) } if (looking_at(&p, "clear depth ")) { - if (!parse_floats(&p, &data->clear_depth, 1, NULL)) + if (!parse_floats(data, &p, &data->clear_depth, 1, NULL)) goto error; if (!is_end(p)) goto error; @@ -1725,14 +1746,10 @@ process_test_line(struct load_state *data) if (process_draw_rect_command(data, p, command)) return true; - if (process_probe_command(p, - command, - &data->tolerance)) + if (process_probe_command(data, p, command)) return true; - if (process_probe_ssbo_command(p, - command, - &data->tolerance)) + if (process_probe_ssbo_command(data, p, command)) return true; if (looking_at(&p, "draw arrays ")) @@ -1781,7 +1798,8 @@ process_test_line(struct load_state *data) goto error; if (!parse_size_t(&p, &command->set_push_constant.offset)) goto error; - if (!parse_buffer_subdata(&p, + if (!parse_buffer_subdata(data, + &p, type, &command->set_push_constant.size, &command->set_push_constant.data)) diff --git a/vkrunner/vr-strtof.c b/vkrunner/vr-strtof.c new file mode 100644 index 0000000..95f01e9 --- /dev/null +++ b/vkrunner/vr-strtof.c @@ -0,0 +1,80 @@ +/* + * vkrunner + * + * Copyright (C) 2018 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#define _GNU_SOURCE + +#include "vr-strtof.h" + +#include + +#ifdef __GLIBC__ +#include +#endif + +void +vr_strtof_init(struct vr_strtof_data *data) +{ +#ifdef __GLIBC__ + *(locale_t *) data = newlocale(LC_CTYPE_MASK, "C", NULL); +#endif +} + +float +vr_strtof(const struct vr_strtof_data *data, + const char *nptr, + char **endptr) +{ +#ifdef __GLIBC__ + locale_t c_locale = *(locale_t *) data; + if (c_locale) + return strtof_l(nptr, endptr, c_locale); +#endif + return strtof(nptr, endptr); +} + +double +vr_strtod(const struct vr_strtof_data *data, + const char *nptr, + char **endptr) +{ +#ifdef __GLIBC__ + locale_t c_locale = *(locale_t *) data; + if (c_locale) + return strtod_l(nptr, endptr, c_locale); +#endif + return strtod(nptr, endptr); +} + +void +vr_strtof_destroy(struct vr_strtof_data *data) +{ +#ifdef __GLIBC__ + locale_t c_locale = *(locale_t *) data; + if (c_locale) + freelocale(c_locale); +#endif +} diff --git a/vkrunner/vr-strtof.h b/vkrunner/vr-strtof.h new file mode 100644 index 0000000..beb47fe --- /dev/null +++ b/vkrunner/vr-strtof.h @@ -0,0 +1,59 @@ +/* + * vkrunner + * + * Copyright (C) 2018 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef VR_STRTOF_H +#define VR_STRTOF_H + +#include + +/* This union has enough space to hold whatever locale_t is. We don’t + * want to actually use locale_t because we want to confine + * _GNU_SOURCE to vr-strtof.c so that we don’t accidentally break + * portability. + */ +struct vr_strtof_data { + union { + void *pointer; + uint64_t integer; + }; +}; + +void +vr_strtof_init(struct vr_strtof_data *data); + +float +vr_strtof(const struct vr_strtof_data *data, + const char *nptr, + char **endptr); + +double +vr_strtod(const struct vr_strtof_data *data, + const char *nptr, + char **endptr); + +void +vr_strtof_destroy(struct vr_strtof_data *data); + +#endif /* VR_STRTOF_H */ diff --git a/vkrunner/vr-vbo.c b/vkrunner/vr-vbo.c index 255ec81..bd8cf7f 100644 --- a/vkrunner/vr-vbo.c +++ b/vkrunner/vr-vbo.c @@ -262,7 +262,10 @@ parse_datum(const struct vr_config *config, case VR_FORMAT_MODE_SFLOAT: switch (bit_size) { case 16: { - unsigned short value = vr_hex_strtohf(*text, &endptr); + unsigned short value = + vr_hex_strtohf(&config->strtof_data, + *text, + &endptr); if (errno == ERANGE) { vr_error_message(config, "Could not parse as " @@ -273,7 +276,9 @@ parse_datum(const struct vr_config *config, goto handled; } case 32: { - float value = vr_hex_strtof(*text, &endptr); + float value = vr_hex_strtof(&config->strtof_data, + *text, + &endptr); if (errno == ERANGE) { vr_error_message(config, "Could not parse as float"); @@ -283,7 +288,9 @@ parse_datum(const struct vr_config *config, goto handled; } case 64: { - double value = vr_hex_strtod(*text, &endptr); + double value = vr_hex_strtod(&config->strtof_data, + *text, + &endptr); if (errno == ERANGE) { vr_error_message(config, "Could not parse as double");