From: W. Trevor King Date: Thu, 13 Aug 2009 10:09:42 +0000 (-0400) Subject: Safer string to number conversion with ato*() -> safe_strto*(). X-Git-Tag: v0.9~4 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=f6449a7981b22b2246d2acd016dfce7aba62a85d;p=sawsim.git Safer string to number conversion with ato*() -> safe_strto*(). Current hack to avoid including string.h for strlen() in every *.c file that uses safe_strto*(), which I should fix when I pull them out into utils.h/c files or similar. --- diff --git a/.be/bugs/c41489cf-8225-42a5-adf5-ee6761e45bd8/comments/1cda0419-ce8c-452c-9aac-75b18f5ee4f3/body b/.be/bugs/c41489cf-8225-42a5-adf5-ee6761e45bd8/comments/1cda0419-ce8c-452c-9aac-75b18f5ee4f3/body new file mode 100644 index 0000000..a459f86 --- /dev/null +++ b/.be/bugs/c41489cf-8225-42a5-adf5-ee6761e45bd8/comments/1cda0419-ce8c-452c-9aac-75b18f5ee4f3/body @@ -0,0 +1,8 @@ +Fixed in the ato*() -> safe_strto*() transition. +Now the error message looks like: + +$ bin/sawsim -v1 -s A,null -N -s B,null -k A,B,const,1 +Error: unparsable '-s' while parsing '-s' for -N +sawsim: build/sawsim.c:720: safe_strtoi: Assertion `endp == ((void *)0)' failed. +Aborted + diff --git a/.be/bugs/c41489cf-8225-42a5-adf5-ee6761e45bd8/comments/1cda0419-ce8c-452c-9aac-75b18f5ee4f3/values b/.be/bugs/c41489cf-8225-42a5-adf5-ee6761e45bd8/comments/1cda0419-ce8c-452c-9aac-75b18f5ee4f3/values new file mode 100644 index 0000000..ade20bc --- /dev/null +++ b/.be/bugs/c41489cf-8225-42a5-adf5-ee6761e45bd8/comments/1cda0419-ce8c-452c-9aac-75b18f5ee4f3/values @@ -0,0 +1,11 @@ +Author: W. Trevor King + + +Content-type: text/plain + + +Date: Thu, 13 Aug 2009 10:08:57 +0000 + + +In-reply-to: 0aca6729-b1ed-4eeb-9347-28dcee29b588 + diff --git a/.be/bugs/c41489cf-8225-42a5-adf5-ee6761e45bd8/values b/.be/bugs/c41489cf-8225-42a5-adf5-ee6761e45bd8/values index ced2a81..4d60cd7 100644 --- a/.be/bugs/c41489cf-8225-42a5-adf5-ee6761e45bd8/values +++ b/.be/bugs/c41489cf-8225-42a5-adf5-ee6761e45bd8/values @@ -7,7 +7,7 @@ reporter: W. Trevor King severity: minor -status: open +status: fixed summary: list_element fails when -N eats s argument... diff --git a/src/sawsim.nw b/src/sawsim.nw index 1132a9f..be36e71 100644 --- a/src/sawsim.nw +++ b/src/sawsim.nw @@ -899,6 +899,7 @@ void help(char *prog_name, double P, double t_max, double dt_max, double v, doub \label{sec.get_options} <>= +<> void get_options(int argc, char **argv, double *pP, double *pT_max, double *pDt_max, double *pV, double *pX_step, state_t **pStop_state, environment_t *env, @@ -959,13 +960,13 @@ void get_options(int argc, char **argv, } } break; - case 't': *pT_max = atof(optarg); break; - case 'd': *pDt_max = atof(optarg); break; - case 'P': *pP = atof(optarg); break; - case 'v': *pV = atof(optarg); break; - case 'x': *pX_step = atof(optarg); break; - case 'T': env->T = atof(optarg); break; - case 'C': env->T = atof(optarg)+273.15; break; + case 't': *pT_max = safe_strtod(optarg, "-t"); break; + case 'd': *pDt_max = safe_strtod(optarg, "-d"); break; + case 'P': *pP = safe_strtod(optarg, "-P"); break; + case 'v': *pV = safe_strtod(optarg, "-v"); break; + case 'x': *pX_step = safe_strtod(optarg, "-x"); break; + case 'T': env->T = safe_strtod(optarg, "-T"); break; + case 'C': env->T = safe_strtod(optarg, "-C")+273.15; break; case 's': parse_list_string(optarg, SEP, '{', '}', &num_strings, &strings); assert(num_strings >= 2 && num_strings <= 4); @@ -977,7 +978,7 @@ void get_options(int argc, char **argv, } tension_model = index_tension_model(n_tension_models, tension_models, strings[1]); if (num_strings == 4) - tension_group = atoi(strings[2]); + tension_group = safe_strtoi(strings[2], optarg); else tension_group = 0; if (num_strings >= 3) @@ -998,7 +999,7 @@ void get_options(int argc, char **argv, free_parsed_list(num_strings, strings); break; case 'N': - n = atoi(optarg); + n = safe_strtoi(optarg, "-N"); #ifdef DEBUG fprintf(stderr, "%s:\tadding %d domains to %s\n", __FUNCTION__, n, S(*pState_list)->name); #endif @@ -1109,6 +1110,47 @@ int index_k_model(int n_models, k_model_getopt_t *models, char *name) } while (0); @ +First we define some safe string parsing functions. Currently these +abort on any irregularity, but in the future they could print error +messages, etc. [[static]] because the functions are currently +defined in each [[*.c]] file that uses them, but perhaps they should +be moved to [[utils.h/c]] or some such instead\ldots + +<>= +static int safe_strtoi(const char *s, const char *description) { + char *endp = NULL; + long int ret; + assert(s != NULL); + ret = strtol(s, &endp, 10); + if (endp[0] != '\0') { //strlen(endp) > 0) { + fprintf(stderr, "Error: unparsable '%s' while parsing '%s' for %s\n", + endp, s, description); + assert(1==0); //strlen(endp) == 0); + } else if (errno == ERANGE) { + fprintf(stderr, "Error: '%s' out of range for %s\n", s, description); + assert(errno != ERANGE); + } + return (int) ret; +} + +static double safe_strtod(const char *s, const char *description) { + char *endp = NULL; + double ret; + assert(s != NULL); + ret = strtod(s, &endp); + if (endp[0] != '\0') { //strlen(endp) > 0) { + fprintf(stderr, "Error: unparsable '%s' while parsing '%s' for %s\n", + endp, s, description); + assert(1==0); //strlen(endp) == 0); + } else if (errno == ERANGE) { + fprintf(stderr, "Error: '%s' out of range for %s\n", s, description); + assert(errno != ERANGE); + } + return ret; +} + +@ + \phantomsection \appendix \addcontentsline{toc}{section}{Appendicies} @@ -1131,12 +1173,13 @@ The general layout of our simulation code is: We include [[math.h]], so don't forget to link to the libm with `-lm'. <>= #include /* assert() */ -#include /* malloc(), free(), rand() */ +#include /* malloc(), free(), rand(), strto*() */ #include /* fprintf(), stdout */ #include /* strlen, strtok() */ #include /* exp(), M_PI, sqrt() */ #include /* pid_t (returned by getpid()) */ #include /* getpid() (for seeding rand()), getopt() */ +#include /* errno, ERANGE (for safe_strto*()) */ #include "global.h" #include "list.h" #include "tension_balance.h" @@ -1916,10 +1959,10 @@ Here we check to make sure the various functions work as expected, using \citeta @ <>= -#include /* EXIT_SUCCESS and EXIT_FAILURE, atof() */ -#include /* printf() */ -#include /* assert() */ -#include /* strlen() */ +#include /* EXIT_SUCCESS and EXIT_FAILURE */ +#include /* printf() */ +#include /* assert() */ +#include /* strlen() */ <> #include "parse.h" @ @@ -3398,11 +3441,11 @@ Here we check to make sure the various functions work as expected, using \citeta @ <>= -#include /* EXIT_SUCCESS and EXIT_FAILURE, atof() */ -#include /* printf() */ -#include /* assert() */ -#include /* strlen() */ -#include /* SIGKILL */ +#include /* EXIT_SUCCESS and EXIT_FAILURE */ +#include /* printf() */ +#include /* assert() */ +#include /* strlen() */ +#include /* SIGKILL */ <> #include "string_eval.h" @ @@ -3720,7 +3763,8 @@ const_tension_param_t *create_const_tension_param_t(double F) void *string_create_const_tension_param_t(char **param_strings) { - return create_const_tension_param_t(atof(param_strings[0])); + return create_const_tension_param_t( + safe_strtod(param_strings[0],__FUNCTION__)); } void destroy_const_tension_param_t(void *p) @@ -3858,7 +3902,7 @@ hooke_param_t *create_hooke_param_t(double k) void *string_create_hooke_param_t(char **param_strings) { - return create_hooke_param_t(atof(param_strings[0])); + return create_hooke_param_t(safe_strtod(param_strings[0], __FUNCTION__)); } void destroy_hooke_param_t(void *p) @@ -4093,7 +4137,8 @@ wlc_param_t *create_wlc_param_t(double p, double L) void *string_create_wlc_param_t(char **param_strings) { - return create_wlc_param_t(atof(param_strings[0]), atof(param_strings[1])); + return create_wlc_param_t(safe_strtod(param_strings[0], __FUNCTION__), + safe_strtod(param_strings[1], __FUNCTION__)); } void destroy_wlc_param_t(void *p /* wlc_param_t * */) @@ -4235,7 +4280,8 @@ fjc_param_t *create_fjc_param_t(double l, double N) void *string_create_fjc_param_t(char **param_strings) { - return create_fjc_param_t(atof(param_strings[0]), atof(param_strings[1])); + return create_fjc_param_t(safe_strtod(param_strings[0], __FUNCTION__), + safe_strtod(param_strings[1], __FUNCTION__)); } void destroy_fjc_param_t(void *p) @@ -4275,9 +4321,10 @@ char fjc_param_string[]="0.5e-9,200"; <>= #include /* assert() */ -#include /* NULL */ +#include /* NULL, strto*() */ #include /* HUGE_VAL, sqrt(), exp() */ #include /* fprintf(), stdout */ +#include /* errno, ERANGE */ #include "global.h" #include "list.h" #include "tension_balance.h" /* oneD_*() */ @@ -4299,6 +4346,7 @@ char fjc_param_string[]="0.5e-9,200"; @ <>= +<> <> <> <> @@ -4381,8 +4429,9 @@ int main(int argc, char **argv) <>= #include #include -#include /* strlen() */ -#include /* assert() */ +#include /* strlen() */ +#include /* assert() */ +#include /* errno, ERANGE */ #include "global.h" #include "parse.h" #include "list.h" @@ -4399,6 +4448,7 @@ int main(int argc, char **argv) @ <>= +<> <> <> <> @@ -4459,16 +4509,16 @@ void get_options(int argc, char **argv, environment_t *env, /* setup defaults */ prog_name = argv[0]; - env->T = 300.0; /* K */ - *Fmax = 1e5; - *Xmax = 1e-6; + env->T = 300.0; /* K */ + *Fmax = 1e5; /* N */ + *Xmax = 1e-6; /* m */ *flags = 0; *model = tension_models; while ((c=getopt(argc, argv, options)) != -1) { switch(c) { - case 'T': env->T = atof(optarg); break; - case 'C': env->T = atof(optarg)+273.15; break; + case 'T': env->T = safe_strtod(optarg, "-T"); break; + case 'C': env->T = safe_strtod(optarg, "-C")+273.15; break; case 'm': tension_model = index_tension_model(n_tension_models, tension_models, optarg); *model = tension_models+tension_model; @@ -4476,9 +4526,9 @@ void get_options(int argc, char **argv, environment_t *env, case 'a': tension_models[tension_model].params = optarg; break; - case 'F': *Fmax = atof(optarg); break; - case 'X': *Xmax = atof(optarg); break; - case 'V': *flags |= VFLAG; break; + case 'F': *Fmax = safe_strtod(optarg, "-F"); break; + case 'X': *Xmax = safe_strtod(optarg, "-X"); break; + case 'V': *flags |= VFLAG; break; case '?': fprintf(stderr, "unrecognized option '%c'\n", optopt); /* fall through to default case */ @@ -4621,7 +4671,7 @@ const_k_param_t *create_const_k_param_t(double knot) void *string_create_const_k_param_t(char **param_strings) { - return create_const_k_param_t(atof(param_strings[0])); + return create_const_k_param_t(safe_strtod(param_strings[0], __FUNCTION__)); } void destroy_const_k_param_t(void *p /* const_k_param_t * */) @@ -4717,7 +4767,8 @@ bell_param_t *create_bell_param_t(double knot, double dx) void *string_create_bell_param_t(char **param_strings) { - return create_bell_param_t(atof(param_strings[0]), atof(param_strings[1])); + return create_bell_param_t(safe_strtod(param_strings[0], __FUNCTION__), + safe_strtod(param_strings[1], __FUNCTION__)); } void destroy_bell_param_t(void *p /* bell_param_t * */) @@ -4817,7 +4868,8 @@ kbell_param_t *create_kbell_param_t(double knot, double dx) void *string_create_kbell_param_t(char **param_strings) { - return create_kbell_param_t(atof(param_strings[0]), atof(param_strings[1])); + return create_kbell_param_t(safe_strtod(param_strings[0], __FUNCTION__), + safe_strtod(param_strings[1], __FUNCTION__)); } void destroy_kbell_param_t(void *p /* kbell_param_t * */) @@ -4922,7 +4974,7 @@ double kramers_x_fn(FILE *in, FILE *out, char *fn, double F, double T) fprintf(in, "F = %g; T = %g\n", F, T); sprintf(input, "print repr(%s)\n", fn); /* repr() to keep full precision */ string_eval(in, out, input, 80, output); - return atof(output); + return safe_strtod(output, __FUNCTION__); } double kramers_E_fn(FILE *in, FILE *out, char *fn, double F, double T, double x) @@ -4933,7 +4985,7 @@ double kramers_E_fn(FILE *in, FILE *out, char *fn, double F, double T, double x) fprintf(in, "F = %g;T = %g;x = %g\n", F, T, x); sprintf(input, "print repr(%s)\n", fn); /* repr() to keep full precision */ string_eval(in, out, input, 80, output); - return atof(output); + return safe_strtod(output, __FUNCTION__); } double kramers_E(double F, environment_t *env, void *kramers_params, double x) @@ -5010,7 +5062,7 @@ kramers_param_t *create_kramers_param_t(double D, /* takes an array of 4 functions: {"(1,2),(2,0),..."} */ void *string_create_kramers_param_t(char **param_strings) { - return create_kramers_param_t(atof(param_strings[0]), + return create_kramers_param_t(safe_strtod(param_strings[0], __FUNCTION__), param_strings[2], param_strings[3], param_strings[4], @@ -5247,11 +5299,11 @@ void *string_create_kramers_integ_param_t(char **param_strings) //printf("create kramers integ. D: %s, knots: %s, x in [%s, %s]\n", // param_strings[0],param_strings[1],param_strings[2],param_strings[3]); void *E_params = string_create_spline_param_t(param_strings+1); - return create_kramers_integ_param_t(atof(param_strings[0]), - atof(param_strings[2]), - atof(param_strings[3]), - &spline_eval, E_params, - destroy_spline_param_t); + return create_kramers_integ_param_t( + safe_strtod(param_strings[0], __FUNCTION__), + safe_strtod(param_strings[2], __FUNCTION__), + safe_strtod(param_strings[3], __FUNCTION__), + &spline_eval, E_params, destroy_spline_param_t); } void destroy_kramers_integ_param_t(void *params) @@ -5373,11 +5425,12 @@ Initialized with Titin I27 parameters\citep{carrion-vazquez99b}. @ <>= -#include /* assert() */ -#include /* NULL, malloc() */ -#include /* HUGE_VAL, sqrt(), exp() */ -#include /* fprintf(), stdout */ -#include /* strlen(), strcpy() */ +#include /* assert() */ +#include /* NULL, malloc(), strto*() */ +#include /* HUGE_VAL, sqrt(), exp() */ +#include /* fprintf(), stdout */ +#include /* strlen(), strcpy() */ +#include /* errno, ERANGE */ #include #include #include "global.h" @@ -5403,6 +5456,7 @@ Initialized with Titin I27 parameters\citep{carrion-vazquez99b}. @ <>= +<> <> <> <> @@ -5423,16 +5477,18 @@ Here we check to make sure the various functions work as expected, using \citeta @ <>= -#include /* EXIT_SUCCESS and EXIT_FAILURE, atof() */ -#include /* sprintf() */ -#include /* assert() */ -#include /* exp() */ +#include /* EXIT_SUCCESS, EXIT_FAILURE */ +#include /* sprintf() */ +#include /* assert() */ +#include /* exp() */ +#include /* errno, ERANGE */ <> #include "global.h" #include "k_model.h" @ <>= +<> <> <> <> @@ -5493,7 +5549,7 @@ START_TEST(test_const_k_over_range) params[0] = knot[i]; p = string_create_const_k_param_t(params); for ( F=Fm; F>= #include #include -#include /* strlen() */ -#include /* assert() */ +#include /* strlen() */ +#include /* assert() */ +#include /* errno, ERANGE */ #include "global.h" #include "parse.h" #include "string_eval.h" @@ -5731,6 +5788,7 @@ enum mode_t {M_K_OF_F, M_SPECIAL}; @ <>= +<> <> <> <> @@ -5800,18 +5858,18 @@ void get_options(int argc, char **argv, environment_t *env, /* setup defaults */ prog_name = argv[0]; - env->T = 300.0; /* K */ + env->T = 300.0; /* K */ *mode = M_K_OF_F; *flags = 0; *model = k_models; - *Fmax = 1e-9; + *Fmax = 1e-9; /* N */ *special_xmax = 1e-8; *special_xmin = 0.0; while ((c=getopt(argc, argv, options)) != -1) { switch(c) { - case 'T': env->T = atof(optarg); break; - case 'C': env->T = atof(optarg)+273.15; break; + case 'T': env->T = safe_strtod(optarg, "-T"); break; + case 'C': env->T = safe_strtod(optarg, "-C")+273.15; break; case 'k': k_model = index_k_model(n_k_models, k_models, optarg); *model = k_models+k_model; @@ -5819,12 +5877,12 @@ void get_options(int argc, char **argv, environment_t *env, case 'K': k_models[k_model].params = optarg; break; - case 'm': *mode = M_K_OF_F; break; - case 'M': *mode = M_SPECIAL; break; - case 'F': *Fmax = atof(optarg); break; - case 'x': *special_xmin = atof(optarg); break; - case 'X': *special_xmax = atof(optarg); break; - case 'V': *flags |= VFLAG; break; + case 'm': *mode = M_K_OF_F; break; + case 'M': *mode = M_SPECIAL; break; + case 'F': *Fmax = safe_strtod(optarg, "-F"); break; + case 'x': *special_xmin = safe_strtod(optarg, "-x"); break; + case 'X': *special_xmax = safe_strtod(optarg, "-X"); break; + case 'V': *flags |= VFLAG; break; case '?': fprintf(stderr, "unrecognized option '%c'\n", optopt); /* fall through to default case */