diff --git a/src/common/func.c b/src/common/func.c index bad5f11..1e1e999 100644 --- a/src/common/func.c +++ b/src/common/func.c @@ -45,6 +45,7 @@ extern char *strdup(const char* s); #else #define CONST_PI ((double)3.14159265358979323846) #endif + /*}}}*/ #ifdef WIN32 @@ -304,6 +305,11 @@ static double deg2rad(double x) } /*}}}*/ +static void duperror(Token* tok, const char* erro) { + tok->type = EEK; + tok->u.err = strdup(erro); +} + typedef enum {ABSOLUTE, RELATIVE, EXCEL} LocConvention; static Token excel_adr_func(int argc, const Token argv[]); @@ -340,12 +346,8 @@ static Token adr_func(int argc, const Token argv[], LocConvention lcon) else if (argv[i].type != EMPTY) break; } if (i < argc) - { - result.type=EEK; - result.u.err=strcpy(malloc(strlen(_("Usage: &([integer x][,[integer y][,[integer z]]])"))+1),_("Usage: &([integer x][,[integer y][,[integer z]]])")); - } - else - result.type = LOCATION; + duperror(&result, _("Usage: &([integer x][,[integer y][,[integer z]]])")); + else result.type = LOCATION; return result; } /*}}}*/ @@ -408,16 +410,14 @@ static Token excel_adr_func(int argc, const Token argv[]) Token result; char *usage = _("Usage: X&(THERE_LABEL, HERE_LABEL, [fix_x], [fix_y], [fix_z])"); if (argc < 2) { - result.type = EEK; - result.u.err = strdup(usage); + duperror(&result, usage); return result; } if (argv[0].type == EEK) return argv[0]; if (argv[1].type == EEK) return argv[1]; if (argv[0].type != LOCATION || argv[1].type != LOCATION) { - result.type = EEK; - result.u.err = strdup(usage); + duperror(&result, usage); return result; } @@ -432,8 +432,7 @@ static Token excel_adr_func(int argc, const Token argv[]) if (argv[i].type == EEK) return argv[i]; if (!INTPATIBLE(argv[i])) { - result.type = EEK; - result.u.err = strdup(usage); + duperror(&result, usage); return result; } if (argv[i].type == INT && argv[i].u.integer > 0) fixed = true; @@ -503,9 +502,7 @@ static Token bitwise_func(int argc, const Token argv[], LogicalFunction lop) for (size_t i = 0; i < argc; ++i) { if (!INTPATIBLE(argv[i])) { - result.type = EEK; - result.u.err = - strdup(_("Bitwise functions operate only on integers.")); + duperror(&result, _("Bitwise functions operate only on integers.")); return result; } int val = 0; @@ -541,15 +538,11 @@ static Token e_func(int argc, const Token argv[]) result.u.flt=CONST_E; } /*}}}*/ - else /* result is e type error */ /*{{{*/ - { - result.type=EEK; - result.u.err=strdup(_("Usage: e()")); - } - /*}}}*/ + else duperror(&result, _("Usage: e()")); return result; } /*}}}*/ + /* eval */ /*{{{*/ static Token eval_func(int argc, const Token argv[]) { @@ -558,13 +551,7 @@ static Token eval_func(int argc, const Token argv[]) /*}}}*/ --max_eval; - if (max_eval<0) - /* nesting error */ /*{{{*/ - { - result.type=EEK; - result.u.err=strdup(_("nested eval()")); - } - /*}}}*/ + if (max_eval<0) duperror(&result, _("nested eval()")); else if (argc==1 && argv[0].type==LOCATION) /* evaluate expression in cell at given position */ /*{{{*/ { @@ -577,13 +564,7 @@ static Token eval_func(int argc, const Token argv[]) else result=eval(contents); } /*}}}*/ - else - /* eval type error */ /*{{{*/ - { - result.type=EEK; - result.u.err=strcpy(malloc(strlen(_("Usage: eval(location)"))+1),_("Usage: eval(location)")); - } - /*}}}*/ + else duperror(&result, _("Usage: eval(location)")); ++max_eval; return result; } @@ -599,15 +580,9 @@ static Token error_func(int argc, const Token argv[]) /* asserts */ /*{{{*/ assert(argv!=(Token*)0); /*}}}*/ - result.type=EEK; - if (argc!=1 || argv[0].type!=STRING) - /* result is type error */ /*{{{*/ - result.u.err=strcpy(malloc(strlen(_("Usage: error(string message)"))+1),_("Usage: error(string message)")); - /*}}}*/ - else - /* result is user defined error */ /*{{{*/ - result.u.err=strcpy(malloc(strlen(argv[0].u.string)+1),argv[0].u.string); - /*}}}*/ + if (argc != 1 || argv[0].type != STRING) + duperror(&result, _("Usage: error(string message)")); + else duperror(&result, argv[0].u.string); return result; } /*}}}*/ @@ -673,22 +648,21 @@ static Token string_func(int argc, const Token argv[]) } /*}}}*/ else /* return string type error */ /*{{{*/ - { - result.type=EEK; - result.u.err=strcpy(malloc(strlen(_("Usage: string(location) or string(float[,[integer][,integer]])"))+1),_("Usage: string(location) or string(float[,[integer][,integer]])")); - return result; - } - /*}}}*/ + duperror(&result, _("Usage: string(location)|string(int)|string(float[,[int][,integer]])")); return result; } /*}}}*/ + /* sum */ /*{{{*/ static Token sum_func(int argc, const Token argv[]) { - /* variables */ /*{{{*/ Token result; - /*}}}*/ + const char *usage = _("Usage: sum(loc_start, loc_end)|sum(val1, val2,...)"); + if (argc == 0) { + duperror(&result, usage); + return result; + } if (argc==2 && argv[0].type==LOCATION && argv[1].type==LOCATION) /* result is sum */ /*{{{*/ { /* variables */ /*{{{*/ @@ -714,17 +688,22 @@ static Token sum_func(int argc, const Token argv[]) result=tmp; if (result.type==EEK) return result; } + } else { + Token tmp; + /* Try to add up the args */ + result = tcopy(argv[0]); + for (size_t i = 1; i < argc; ++i) + { + tmp = tadd(result, argv[i]); + tfree(&result); + result = tmp; + if (result.type == EEK) return result; + } } - /*}}}*/ - else /* result is sum type error */ /*{{{*/ - { - result.type=EEK; - result.u.err=strcpy(malloc(strlen(_("Usage: sum(location,location)"))+1),_("Usage: sum(location,location)")); - } - /*}}}*/ return result; } /*}}}*/ + /* n */ /*{{{*/ static Token n_func(int argc, const Token argv[]) { @@ -759,13 +738,7 @@ static Token n_func(int argc, const Token argv[]) result.u.integer = n; } /*}}}*/ - else - /* result is n type error */ /*{{{*/ - { - result.type=EEK; - result.u.err=strcpy(malloc(strlen(_("Usage: n(location,location)"))+1),_("Usage: n(location,location)")); - } - /*}}}*/ + else duperror(&result, _("Usage: n(location,location)")); return result; } /*}}}*/ @@ -813,29 +786,18 @@ static Token int_func(int argc, const Token argv[]) errno=0; result.u.integer=strtol(argv[0].u.string,&s,10); - if (s==(char*)0 || *s) - { - result.type=EEK; - result.u.err=strdup(_("int(string): invalid string")); - } - else if (errno==ERANGE && (result.u.integer==LONG_MAX || result.u.integer==LONG_MIN)) - { - result.type=EEK; - result.u.err=strdup(_("int(string): domain error")); - } + if (s==(char*)0 || *s) duperror(&result, _("int(string): invalid string")); + else if (errno==ERANGE && + (result.u.integer==LONG_MAX || result.u.integer==LONG_MIN)) + duperror(&result, _("int(string): domain error")); else result.type=INT; } /*}}}*/ - else - /* result is int type error */ /*{{{*/ - { - result.type=EEK; - result.u.err=strcpy(malloc(strlen(_("Usage: int(float[,integer,integer])"))+1),_("Usage: int(float[,integer,integer])")); - } - /*}}}*/ + else duperror(&result, _("Usage: int(float[,integer,integer])")); return result; } /*}}}*/ + /* frac */ /*{{{*/ static Token frac_func(int argc, const Token argv[]) { @@ -851,16 +813,11 @@ static Token frac_func(int argc, const Token argv[]) result.u.flt=modf(argv[0].u.flt,&foo); } /*}}}*/ - else - /* result is frac type error */ /*{{{*/ - { - result.type=EEK; - result.u.err=strcpy(malloc(strlen(_("Usage: frac(float)"))+1),_("Usage: frac(float)")); - } - /*}}}*/ + else duperror(&result, _("Usage: frac(float)")); return result; } /*}}}*/ + /* len */ /*{{{*/ static Token len_func(int argc, const Token argv[]) { @@ -875,13 +832,7 @@ static Token len_func(int argc, const Token argv[]) result.u.integer=strlen(argv[0].u.string); } /*}}}*/ - else - /* result is frac type error */ /*{{{*/ - { - result.type=EEK; - result.u.err=strdup(_("Usage: len(string)")); - } - /*}}}*/ + else duperror(&result, _("Usage: len(string)")); return result; } /*}}}*/ @@ -919,15 +870,11 @@ static Token log_func(int argc, const Token argv[]) else result.u.flt=log(x)/log(y); } /*}}}*/ - else /* result is log type error */ /*{{{*/ - { - result.type=EEK; - result.u.err=strdup(_("Usage: log(float[,float])")); - } - /*}}}*/ + else duperror(&result, _("Usage: log(float[,float])")); return result; } /*}}}*/ + /* minmax */ /*{{{*/ static Token minmax_func(int argc, const Token argv[], int min) { @@ -1005,15 +952,13 @@ static Token minmax_func(int argc, const Token argv[], int min) return argv[mini]; } else - /* result is min/max type error */ /*{{{*/ - { - result.type=EEK; - result.u.err=strdup(min ? _("Usage: min(location,location) or min(val1, val2,...)") : _("Usage: max(location,location) or max(val1,val2,...)")); - return result; - } - /*}}}*/ + duperror(&result, + min ? _("Usage: min(location,location) or min(val1, val2,...)") + : _("Usage: max(location,location) or max(val1,val2,...)")); + return result; } /*}}}*/ + /* min */ /*{{{*/ static Token min_func(int argc, const Token argv[]) { @@ -1047,13 +992,7 @@ static Token abs_func(int argc, const Token argv[]) result.u.integer=(argv[0].u.integer<0 ? -argv[0].u.integer : argv[0].u.integer); } /*}}}*/ - else - /* result is abs type error */ /*{{{*/ - { - result.type=EEK; - result.u.err=strdup(_("Usage: abs(float|integer)")); - } - /*}}}*/ + else duperror(&result, _("Usage: abs(float|integer)")); return result; } /*}}}*/ @@ -1072,14 +1011,11 @@ static Token env_func(int argc, const Token argv[]) result.type=STRING; result.u.string=strdup(e); } - else - { - result.type=EEK; - result.u.err=strdup(_("Usage: $(string)")); - } + else duperror(&result, _("Usage: $(string)")); return result; } /*}}}*/ + /* float */ /*{{{*/ static Token float_func(int argc, const Token argv[]) { @@ -1090,28 +1026,18 @@ static Token float_func(int argc, const Token argv[]) { char *p; - result.u.flt=strtod(argv[0].u.string,&p); - if (p!=argv[0].u.string && *p=='\0' && dblfinite(result.u.flt)==(const char*)0) - { - result.type=FLOAT; - } - else - { - result.type=EEK; - result.u.err=strdup(_("Not a (finite) floating point number")); - } - } - /*}}}*/ - else - /* float type error */ /*{{{*/ - { - result.type=EEK; - result.u.err=strdup(_("Usage: float(string)")); + result.u.flt = strtod(argv[0].u.string, &p); + if (p != argv[0].u.string && *p=='\0' + && dblfinite(result.u.flt) == (const char*)0) + result.type = FLOAT; + else duperror(&result, _("Not a (finite) floating point number")); } /*}}}*/ + else duperror(&result, _("Usage: float(string)")); return result; } /*}}}*/ + /* strftime */ /*{{{*/ static Token strftime_func(int argc, const Token argv[]) { @@ -1147,15 +1073,11 @@ static Token strftime_func(int argc, const Token argv[]) result.type=STRING; } /*}}}*/ - else /* strftime type error */ /*{{{*/ - { - result.type=EEK; - result.u.err=strdup(_("Usage: strftime(string[,integer])")); - } - /*}}}*/ + else duperror(&result, _("Usage: strftime(string[,integer])")); return result; } /*}}}*/ + /* clock */ /*{{{*/ static Token clock_func(int argc, const Token argv[]) { @@ -1191,132 +1113,137 @@ static Token clock_func(int argc, const Token argv[]) result.type=EMPTY; } /*}}}*/ - else /* wrong usage */ /*{{{*/ - { - result.type=EEK; - result.u.err=strdup(_("Usage: clock(condition,location[,location])")); - } - /*}}}*/ + else duperror(&result, _("Usage: clock(condition,location[,location])")); return result; } /*}}}*/ + /* poly */ /*{{{*/ static Token poly_func(int argc, const Token argv[]) { - /* variables */ /*{{{*/ - Token result; - int i; - /*}}}*/ + Token result, tmp; + const char *usage = _("Usage: poly(float|integer,float|integer,...)"); - for (i=0; i