Module: sip-router Branch: andrei/switch Commit: 8c09d09b62681ae4e25709cd291796880dfb91e6 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=8c09d09b...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@iptel.org Date: Thu Feb 19 23:48:34 2009 +0100
script parsing: string switch support
- switch() modified to work on string if the first case contains a string as the label - switch() support for regular expressions. Regular expression are prefixed by `/`. E.g.: switch("a"){ case / ""+"["+"a"+"bc" +"]" : log(1, "case a:a\n"); break; case "b": log(1, "case a:b\n"); break; }
---
cfg.y | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 112 insertions(+), 12 deletions(-)
diff --git a/cfg.y b/cfg.y index e1758bf..0ebb3a9 100644 --- a/cfg.y +++ b/cfg.y @@ -215,7 +215,11 @@ static struct socket_id* mk_listen_id2(struct name_lst*, int, int); static void free_name_lst(struct name_lst* lst); static void free_socket_id_lst(struct socket_id* i);
-static struct case_stms* mk_case_stm(struct rval_expr* ct, struct action* a); +static struct case_stms* mk_case_stm(struct rval_expr* ct, int is_re, + struct action* a, int* err); +static int case_check_type(struct case_stms* stms); +static int case_check_default(struct case_stms* stms); +
%}
@@ -1793,10 +1797,12 @@ ct_rval: rval_expr { $$=0; if (!rve_is_constant($1)){ yyerror("constant expected"); - }else if (!rve_check_type((enum rval_type*)&i_tmp, $1, 0, 0 ,0)){ + /* + } else if (!rve_check_type((enum rval_type*)&i_tmp, $1, 0, 0 ,0)){ yyerror("invalid expression (bad type)"); }else if (i_tmp!=RV_INT){ yyerror("invalid expression type, int expected\n"); + */ }else $$=$1; } @@ -1805,28 +1811,38 @@ single_case: CASE ct_rval COLON actions { $$=0; if ($2==0) yyerror ("bad case label"); - else if (($$=mk_case_stm($2, $4))==0){ - yyerror("internal error: memory allocation failure"); + else if ((($$=mk_case_stm($2, 0, $4, &i_tmp))==0) && (i_tmp==-10)){ + YYABORT; + } + } +| CASE SLASH ct_rval COLON actions { + $$=0; + if ($3==0) yyerror ("bad case label"); + else if ((($$=mk_case_stm($3, 1, $5, &i_tmp))==0) && (i_tmp==-10)){ YYABORT; } } | CASE ct_rval COLON { $$=0; if ($2==0) yyerror ("bad case label"); - else if (($$=mk_case_stm($2, 0))==0){ - yyerror("internal error: memory allocation failure"); + else if ((($$=mk_case_stm($2, 0, 0, &i_tmp))==0) && (i_tmp==-10)){ + YYABORT; + } + } + | CASE SLASH ct_rval COLON { + $$=0; + if ($3==0) yyerror ("bad case label"); + else if ((($$=mk_case_stm($3, 1, 0, &i_tmp))==0) && (i_tmp==-10)){ YYABORT; } } | DEFAULT COLON actions { - if (($$=mk_case_stm(0, $3))==0){ - yyerror("internal error: memory allocation failure"); + if ((($$=mk_case_stm(0, 0, $3, &i_tmp))==0) && (i_tmp=-10)){ YYABORT; } } | DEFAULT COLON { - if (($$=mk_case_stm(0, 0))==0){ - yyerror("internal error: memory allocation failure"); + if ((($$=mk_case_stm(0, 0, 0, &i_tmp))==0) && (i_tmp==-10)){ YYABORT; } } @@ -1854,6 +1870,12 @@ switch_cmd: $$=0; if ($2==0) yyerror("bad expression in switch(...)"); else if ($4==0) yyerror ("bad switch body"); + else if (case_check_default($4)!=0) + yyerror_at(&$2->fpos, "bad switch(): too many " + ""default:" labels\n"); + else if (case_check_type($4)!=0) + yyerror_at(&$2->fpos, "bad switch(): mixed integer and" + " string/RE cases not allowed\n"); else{ $$=mk_action(SWITCH_T, 2, RVE_ST, $2, CASE_ST, $4); if ($$==0) { @@ -2910,15 +2932,52 @@ static void free_socket_id_lst(struct socket_id* lst) }
-static struct case_stms* mk_case_stm(struct rval_expr* ct, struct action* a) +/** create a temporary case statmenet structure. + * *err will be filled in case of error (return == 0): + * -1 - non constant expression + * -2 - expression error (bad type) + * -10 - memory allocation error + */ +static struct case_stms* mk_case_stm(struct rval_expr* ct, int is_re, + struct action* a, int* err) { struct case_stms* s; + struct rval_expr* bad_rve; + enum rval_type type, bad_t, exp_t; + enum match_str_type t; + + t=MATCH_UNKNOWN; + if (ct){ + /* if ct!=0 => case, else if ct==0 is a default */ + if (!rve_is_constant(ct)){ + yyerror_at(&ct->fpos, "non constant expression in case"); + *err=-1; + return 0; + } + if (rve_check_type(&type, ct, &bad_rve, &bad_t, &exp_t)!=1){ + yyerror_at(&ct->fpos, "bad expression: type mismatch:" + " %s instead of %s at (%d,%d)", + rval_type_name(bad_t), rval_type_name(exp_t), + bad_rve->fpos.s_line, bad_rve->fpos.s_col); + *err=-2; + return 0; + } + if (is_re) + t=MATCH_RE; + else if (type==RV_STR) + t=MATCH_STR; + else + t=MATCH_INT; + } + s=pkg_malloc(sizeof(*s)); if (s==0) { - LOG(L_CRIT,"ERROR: cfg. parser: out of memory.\n"); + yyerror("internal error: memory allocation failure"); + *err=-10; } else { memset(s, 0, sizeof(*s)); s->ct_rve=ct; + s->type=t; s->actions=a; s->next=0; s->append=0; @@ -2926,6 +2985,47 @@ static struct case_stms* mk_case_stm(struct rval_expr* ct, struct action* a) return s; }
+ +/* + * @return 0 on success, -1 on error. + */ +static int case_check_type(struct case_stms* stms) +{ + struct case_stms* c; + struct case_stms* s; + + for(c=stms; c ; c=c->next){ + if (!c->ct_rve) continue; + for (s=c->next; s; s=s->next){ + if (!s->ct_rve) continue; + if ((s->type!=c->type) && + !( (c->type==MATCH_STR || c->type==MATCH_RE) && + (s->type==MATCH_STR || s->type==MATCH_RE) ) ){ + yyerror_at(&s->ct_rve->fpos, "type mismatch in case"); + return -1; + } + } + } + return 0; +} + + +/* + * @return 0 on success, -1 on error. + */ +static int case_check_default(struct case_stms* stms) +{ + struct case_stms* c; + int default_no; + + default_no=0; + for(c=stms; c ; c=c->next) + if (c->ct_rve==0) default_no++; + return (default_no<=1)?0:-1; +} + + + /* int main(int argc, char ** argv) {
Hello Andrei,
On 02/20/2009 12:50 AM, Andrei Pelinescu-Onciul wrote:
[...]
script parsing: string switch support
that's great, thanks. From the next example, to understand the the case can take expression that evaluates to static strings or integers?
Now, with while and switch in there I can work to get most of my configs working with sip-router.
Cheers, Daniel
- switch() modified to work on string if the first case contains a string as the label
- switch() support for regular expressions. Regular expression are prefixed by `/`. E.g.: switch("a"){ case / ""+"["+"a"+"bc" +"]" : log(1, "case a:a\n"); break; case "b": log(1, "case a:b\n"); break; }
On Feb 20, 2009 at 11:15, Daniel-Constantin Mierla miconda@gmail.com wrote:
Hello Andrei,
On 02/20/2009 12:50 AM, Andrei Pelinescu-Onciul wrote:
[...]
script parsing: string switch support
that's great, thanks. From the next example, to understand the the case can take expression that evaluates to static strings or integers?
Yes. There are the following restriction:
- case labels must be static (no vars allowed) - in the same switch you can have only one type of case labels: strings or integers (1) - the first case label sets the required type for all the others (so if your first case label is a string => all the other must be strings, if it's an integer all the other must be integers).
(1) - could be changed in some cases (e.g. string case with some int label allowed, which could be automatically converted to string), but I think it would too confusing and I disallowed it (in general having mixed types in a switch() are 99% an error).
I still think that using a different switch() name for strings will be less confusing (e.g. switch() for integers and match() for strings).
Any opinion on how to differentiate regular expressions from strings? Right now a '/' in front means a regular expression (but there's no way to specify case insensitive match for example).
Now, with while and switch in there I can work to get most of my configs working with sip-router.
Warning: the while works only with integers :-)
Andrei
On 20-02 12:22, Andrei Pelinescu-Onciul wrote:
On Feb 20, 2009 at 11:15, Daniel-Constantin Mierla miconda@gmail.com wrote:
Hello Andrei,
On 02/20/2009 12:50 AM, Andrei Pelinescu-Onciul wrote:
[...]
script parsing: string switch support
that's great, thanks. From the next example, to understand the the case can take expression that evaluates to static strings or integers?
Yes. There are the following restriction:
- case labels must be static (no vars allowed)
- in the same switch you can have only one type of case labels: strings or integers (1)
- the first case label sets the required type for all the others
(so if your first case label is a string => all the other must be strings, if it's an integer all the other must be integers).
(1) - could be changed in some cases (e.g. string case with some int label allowed, which could be automatically converted to string), but I think it would too confusing and I disallowed it (in general having mixed types in a switch() are 99% an error).
I would suggest to convert numbers to strings in this case automatically. For most people things get more confusing with the increasing amount of details they have to remember about the configuration language.
This is similar to the difference between if (method == INVITE) and if (method == "INVITE") I guess most people won't be able to tell you the difference if you asked them.
I would not assume that mixed integers and strings are 99% errors, we don't really know what people have in their configuration scripts and why, so this assumption is IMHO not justified.
I still think that using a different switch() name for strings will be less confusing (e.g. switch() for integers and match() for strings).
Yes, I like match for strings better too, especially if regular expression matching is involved.
Any opinion on how to differentiate regular expressions from strings? Right now a '/' in front means a regular expression (but there's no way to specify case insensitive match for example).
How about enclosing regular expressions in a pair of // like in awk or perl. It would be possible to introduce a flag for case-insensitive matching, something like:
i/regex/
For example:
case i/From/:
my two cents, Jan.
On Feb 20, 2009 at 14:03, Jan Janak jan@iptel.org wrote:
On 20-02 12:22, Andrei Pelinescu-Onciul wrote:
On Feb 20, 2009 at 11:15, Daniel-Constantin Mierla miconda@gmail.com wrote:
Hello Andrei,
On 02/20/2009 12:50 AM, Andrei Pelinescu-Onciul wrote:
[...]
script parsing: string switch support
that's great, thanks. From the next example, to understand the the case can take expression that evaluates to static strings or integers?
Yes. There are the following restriction:
- case labels must be static (no vars allowed)
- in the same switch you can have only one type of case labels: strings or integers (1)
- the first case label sets the required type for all the others
(so if your first case label is a string => all the other must be strings, if it's an integer all the other must be integers).
(1) - could be changed in some cases (e.g. string case with some int label allowed, which could be automatically converted to string), but I think it would too confusing and I disallowed it (in general having mixed types in a switch() are 99% an error).
I would suggest to convert numbers to strings in this case automatically. For most people things get more confusing with the increasing amount of details they have to remember about the configuration language.
This would only make sense if we use match() for strings and switch() for ints. Otherwise it would be too confusing. Anyway I don't think the amount of details of the configuration language is ever a problem, as long as one gets meaningful error messages when checking the config (and before ser startup). The other approaches trade-off less config details for guessing what the user intended, which IMO is much more dangerous. Is much better to get meaningful errors when running ser -cf ... , then getting unexpected behaviour at runtime (a very good example for this are typed variables vs. untyped ones or operators that try to guess the type and assume the user made the right choice).
This is similar to the difference between if (method == INVITE) and if (method == "INVITE") I guess most people won't be able to tell you the difference if you asked them.
I would not assume that mixed integers and strings are 99% errors, we don't really know what people have in their configuration scripts and why, so this assumption is IMHO not justified.
I still think that using a different switch() name for strings will be less confusing (e.g. switch() for integers and match() for strings).
Yes, I like match for strings better too, especially if regular expression matching is involved.
Any opinion on how to differentiate regular expressions from strings? Right now a '/' in front means a regular expression (but there's no way to specify case insensitive match for example).
How about enclosing regular expressions in a pair of // like in awk or perl. It would be possible to introduce a flag for case-insensitive matching, something like:A
I tried //, but it produces an extra shift-reduce conflict in the grammar (so it needs at least more testing).
i/regex/
I was thinking more of /regex/i. Unfortunately for this we need a bigger change in the grammar (I don't see an easier way right now). I agree that it would be nicer, but I want to move to something else :-) (so if there are some volunteers for adding the cfg.y support, I can then easily enable the runtime code support for it, everything else is in place).
For example:
case i/From/:
my two cents, Jan.
Andrei
On Friday 20 February 2009, Andrei Pelinescu-Onciul wrote:
[..]
(1) - could be changed in some cases (e.g. string case with some int label allowed, which could be automatically converted to string), but I think it would too confusing and I disallowed it (in general having mixed types in a switch() are 99% an error).
I would suggest to convert numbers to strings in this case automatically. For most people things get more confusing with the increasing amount of details they have to remember about the configuration language.
This would only make sense if we use match() for strings and switch() for ints. Otherwise it would be too confusing. Anyway I don't think the amount of details of the configuration language is ever a problem, as long as one gets meaningful error messages when checking the config (and before ser startup).
Hi Andrei,
the amount of detail in the config language is IMHO important. The developers must document and test every single statement. Every user must read, learn and memorize each statement too.
I regulary need to check the documentation for some special cases in the config when i get asked for a review of some changes a co-worker did, because he still feel not completely confortable after years of administrating SER* systems. During all the time i spend on user channels i really rarely heard the that our server is to slow (only when some real bottlenecks were involved, like DB), the common complain is that the learning curve is too steep. Perhaps i'm lazy, but i'd not say that everybody out there is it too. ;-)
The other approaches trade-off less config details for guessing what the user intended, which IMO is much more dangerous. Is much better to get meaningful errors when running ser -cf ... , then getting unexpected behaviour at runtime (a very good example for this are typed variables vs. untyped ones or operators that try to guess the type and assume the user made the right choice).
I just checked in kamailio, we don't throw an error if one mix strings and ints in a switch case. We also check for a correct type of an integer in a mixed expression, e.g. if its a valid int value. I don't think that we convert them implicitly, as many pseudo-variables hold internally both a string and a integer value, so mixed expression will work just as intended in most cases.
Cheers,
Henning
On Feb 20, 2009 at 15:54, Henning Westerholt henning.westerholt@1und1.de wrote:
On Friday 20 February 2009, Andrei Pelinescu-Onciul wrote:
[..]
(1) - could be changed in some cases (e.g. string case with some int label allowed, which could be automatically converted to string), but I think it would too confusing and I disallowed it (in general having mixed types in a switch() are 99% an error).
I would suggest to convert numbers to strings in this case automatically. For most people things get more confusing with the increasing amount of details they have to remember about the configuration language.
This would only make sense if we use match() for strings and switch() for ints. Otherwise it would be too confusing. Anyway I don't think the amount of details of the configuration language is ever a problem, as long as one gets meaningful error messages when checking the config (and before ser startup).
Hi Andrei,
the amount of detail in the config language is IMHO important. The developers must document and test every single statement. Every user must read, learn and memorize each statement too.
I regulary need to check the documentation for some special cases in the config when i get asked for a review of some changes a co-worker did, because he still feel not completely confortable after years of administrating SER* systems. During all the time i spend on user channels i really rarely heard the that our server is to slow (only when some real bottlenecks were involved, like DB), the common complain is that the learning curve is too steep. Perhaps i'm lazy, but i'd not say that everybody out there is it too. ;-)
Good luck with runtime debugging then :-)
The other approaches trade-off less config details for guessing what the user intended, which IMO is much more dangerous. Is much better to get meaningful errors when running ser -cf ... , then getting unexpected behaviour at runtime (a very good example for this are typed variables vs. untyped ones or operators that try to guess the type and assume the user made the right choice).
I just checked in kamailio, we don't throw an error if one mix strings and ints in a switch case. We also check for a correct type of an integer in a mixed expression, e.g. if its a valid int value. I don't think that we convert them implicitly, as many pseudo-variables hold internally both a string and a integer value, so mixed expression will work just as intended in
Sorry, but that's just broken (mixed expressions).
Andrei
On Friday 20 February 2009, Andrei Pelinescu-Onciul wrote:
This would only make sense if we use match() for strings and switch() for ints. Otherwise it would be too confusing. Anyway I don't think the amount of details of the configuration language is ever a problem, as long as one gets meaningful error messages when checking the config (and before ser startup).
the amount of detail in the config language is IMHO important. The developers must document and test every single statement. Every user must read, learn and memorize each statement too.
I regulary need to check the documentation for some special cases in the config when i get asked for a review of some changes a co-worker did, because he still feel not completely confortable after years of administrating SER* systems. During all the time i spend on user channels i really rarely heard the that our server is to slow (only when some real bottlenecks were involved, like DB), the common complain is that the learning curve is too steep. Perhaps i'm lazy, but i'd not say that everybody out there is it too. ;-)
Good luck with runtime debugging then :-)
Ok, perhaps we just trade this problem for another one.. ;-) Anyway, i'm really curious about other opinions on this topic.
The other approaches trade-off less config details for guessing what the user intended, which IMO is much more dangerous. Is much better to get meaningful errors when running ser -cf ... , then getting unexpected behaviour at runtime (a very good example for this are typed variables vs. untyped ones or operators that try to guess the type and assume the user made the right choice).
I just checked in kamailio, we don't throw an error if one mix strings and ints in a switch case. We also check for a correct type of an integer in a mixed expression, e.g. if its a valid int value. I don't think that we convert them implicitly, as many pseudo-variables hold internally both a string and a integer value, so mixed expression will work just as intended in
Sorry, but that's just broken (mixed expressions).
Yes, i also would not recommend it at all. I was even surprised that it actually parse the configuration file..
Cheers,
Henning
On Feb 20, 2009 at 16:01, Andrei Pelinescu-Onciul andrei@iptel.org wrote:
On Feb 20, 2009 at 15:54, Henning Westerholt henning.westerholt@1und1.de wrote:
On Friday 20 February 2009, Andrei Pelinescu-Onciul wrote:
[..]
(1) - could be changed in some cases (e.g. string case with some int label allowed, which could be automatically converted to string), but I think it would too confusing and I disallowed it (in general having mixed types in a switch() are 99% an error).
I would suggest to convert numbers to strings in this case automatically. For most people things get more confusing with the increasing amount of details they have to remember about the configuration language.
This would only make sense if we use match() for strings and switch() for ints. Otherwise it would be too confusing. Anyway I don't think the amount of details of the configuration language is ever a problem, as long as one gets meaningful error messages when checking the config (and before ser startup).
Hi Andrei,
the amount of detail in the config language is IMHO important. The developers must document and test every single statement. Every user must read, learn and memorize each statement too.
I regulary need to check the documentation for some special cases in the config when i get asked for a review of some changes a co-worker did, because he still feel not completely confortable after years of administrating SER* systems. During all the time i spend on user channels i really rarely heard the that our server is to slow (only when some real bottlenecks were involved, like DB), the common complain is that the learning curve is too steep. Perhaps i'm lazy, but i'd not say that everybody out there is it too. ;-)
Good luck with runtime debugging then :-)
The other approaches trade-off less config details for guessing what the user intended, which IMO is much more dangerous. Is much better to get meaningful errors when running ser -cf ... , then getting unexpected behaviour at runtime (a very good example for this are typed variables vs. untyped ones or operators that try to guess the type and assume the user made the right choice).
I just checked in kamailio, we don't throw an error if one mix strings and ints in a switch case. We also check for a correct type of an integer in a mixed expression, e.g. if its a valid int value. I don't think that we convert them implicitly, as many pseudo-variables hold internally both a string and a integer value, so mixed expression will work just as intended in
Sorry, but that's just broken (mixed expressions).
I don't really understand this argument. Leaving performance and optimizations aside, do you really think is better to guess what the user might have wanted in ambiguous cases, rather then through an error and point him to explain more clearly what he wants (e.g. use match() instead of switch() for strings, or use typed variables)? With the general approach advocated by some people here, a small error when writing the script (e.g. forgetting some "") will be visible only at runtime (and depending where that error is it could take weeks until that branch of the config is reached and the error is triggered). I think this is much worse then having to add a little more "details" to the script (which BTW wouldn't make it any more difficult then any common programming language).
I'd rather have to declare even variable types (e.g. int $a), rather then debugging strange bugs in a script, because I used a var that happens to get a string value at runtime.
In brief I much prefer adding to the script if this helps check its correctness at sr -cf time, rather then trying to be excessively friendly and leaving a lot of potential script bugs pass-through. The ability to be able to tell that the script would behave correctly (as his writer wanted it to) and eliminate ambiguous cases is more important than trying to keep a very reduced script and guessing what the writer really wanted.
Andrei
On Friday 20 February 2009, Andrei Pelinescu-Onciul wrote:
[..]
I just checked in kamailio, we don't throw an error if one mix strings and ints in a switch case. We also check for a correct type of an integer in a mixed expression, e.g. if its a valid int value. I don't think that we convert them implicitly, as many pseudo-variables hold internally both a string and a integer value, so mixed expression will work just as intended in
Sorry, but that's just broken (mixed expressions).
I don't really understand this argument. Leaving performance and optimizations aside, do you really think is better to guess what the user might have wanted in ambiguous cases, rather then through an error and point him to explain more clearly what he wants (e.g. use match() instead of switch() for strings, or use typed variables)?
I think that its important to not make our config script too much like a "real programming language", with types and cast and this stuff. There is are reasons that script languages like python or perl are now widely used instead of e.g. C, even if their dynamic typed nature moves some error checks into run time. The benefits (higher expressiveness that leads to more compact code, fewer bugs because of automatic memory management etc..) outplay the drawbacks, IMHO.
With the general approach advocated by some people here, a small error when writing the script (e.g. forgetting some "") will be visible only at runtime (and depending where that error is it could take weeks until that branch of the config is reached and the error is triggered). I think this is much worse then having to add a little more "details" to the script (which BTW wouldn't make it any more difficult then any common programming language).
Well, many people that uses our script language are not programmers. And even experienced crypto gurus seems to have difficulties with the complexity that common languages bring with it [1]. ;-)
I'd rather have to declare even variable types (e.g. int $a), rather then debugging strange bugs in a script, because I used a var that happens to get a string value at runtime.
In brief I much prefer adding to the script if this helps check its correctness at sr -cf time, rather then trying to be excessively friendly and leaving a lot of potential script bugs pass-through. The ability to be able to tell that the script would behave correctly (as his writer wanted it to) and eliminate ambiguous cases is more important than trying to keep a very reduced script and guessing what the writer really wanted.
I've of course nothing general against eleminating abiguous cases, like in the switch statement. If the user mix strings and int values in the cases, we really should report an error.
Cheers,
Henning
[1] http://blog.fortify.com/blog/fortify/2009/02/20/SHA-3-Round-1
On 02/20/2009 04:54 PM, Henning Westerholt wrote:
On Friday 20 February 2009, Andrei Pelinescu-Onciul wrote:
[..]
(1) - could be changed in some cases (e.g. string case with some int label allowed, which could be automatically converted to string), but I think it would too confusing and I disallowed it (in general having mixed types in a switch() are 99% an error).
I would suggest to convert numbers to strings in this case automatically. For most people things get more confusing with the increasing amount of details they have to remember about the configuration language.
This would only make sense if we use match() for strings and switch() for ints. Otherwise it would be too confusing. Anyway I don't think the amount of details of the configuration language is ever a problem, as long as one gets meaningful error messages when checking the config (and before ser startup).
Hi Andrei,
the amount of detail in the config language is IMHO important. The developers must document and test every single statement. Every user must read, learn and memorize each statement too.
I regulary need to check the documentation for some special cases in the config when i get asked for a review of some changes a co-worker did, because he still feel not completely confortable after years of administrating SER* systems. During all the time i spend on user channels i really rarely heard the that our server is to slow (only when some real bottlenecks were involved, like DB), the common complain is that the learning curve is too steep. Perhaps i'm lazy, but i'd not say that everybody out there is it too. ;-)
The other approaches trade-off less config details for guessing what the user intended, which IMO is much more dangerous. Is much better to get meaningful errors when running ser -cf ... , then getting unexpected behaviour at runtime (a very good example for this are typed variables vs. untyped ones or operators that try to guess the type and assume the user made the right choice).
I just checked in kamailio, we don't throw an error if one mix strings and ints in a switch case.
this is because the most of PVs have the string value as well.
However, I consider that misleading, although I worked a lot the switch. It was planned to fix as the PV callbacks had a parameter for flags.
I would prefer single type case value, and report errors at startup - it is easier to check and optimize. It is better to use a transformation to convert the value to a specific type (e.g., {s.int}).
Cheers, Daniel
We also check for a correct type of an integer in a mixed expression, e.g. if its a valid int value. I don't think that we convert them implicitly, as many pseudo-variables hold internally both a string and a integer value, so mixed expression will work just as intended in most cases.
Cheers,
Henning
sr-dev mailing list sr-dev@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
On 02/20/2009 05:05 PM, Daniel-Constantin Mierla wrote:
On 02/20/2009 04:54 PM, Henning Westerholt wrote:
On Friday 20 February 2009, Andrei Pelinescu-Onciul wrote:
[..]
(1) - could be changed in some cases (e.g. string case with some int label allowed, which could be automatically converted to string), but I think it would too confusing and I disallowed it (in general having mixed types in a switch() are 99% an error).
I would suggest to convert numbers to strings in this case automatically. For most people things get more confusing with the increasing amount of details they have to remember about the configuration language.
This would only make sense if we use match() for strings and switch() for ints. Otherwise it would be too confusing. Anyway I don't think the amount of details of the configuration language is ever a problem, as long as one gets meaningful error messages when checking the config (and before ser startup).
Hi Andrei,
the amount of detail in the config language is IMHO important. The developers must document and test every single statement. Every user must read, learn and memorize each statement too.
I regulary need to check the documentation for some special cases in the config when i get asked for a review of some changes a co-worker did, because he still feel not completely confortable after years of administrating SER* systems. During all the time i spend on user channels i really rarely heard the that our server is to slow (only when some real bottlenecks were involved, like DB), the common complain is that the learning curve is too steep. Perhaps i'm lazy, but i'd not say that everybody out there is it too. ;-)
The other approaches trade-off less config details for guessing what the user intended, which IMO is much more dangerous. Is much better to get meaningful errors when running ser -cf ... , then getting unexpected behaviour at runtime (a very good example for this are typed variables vs. untyped ones or operators that try to guess the type and assume the user made the right choice).
I just checked in kamailio, we don't throw an error if one mix strings and ints in a switch case.
this is because the most of PVs have the string value as well.
However, I consider that misleading, although I worked a lot the switch. It was planned to fix as the PV callbacks had a parameter for flags.
... re-reading ... looks like half explained, so here is more ... the flags parameter was intended to specify what type or value to get from PV (int or str), so the PV callback function does not need to provide the string representation if there is an int behind PV and int is required for the operation.
Now there are some operations done for nothing, inherited because of PV roots in xlog where everything needed to be string represented.
I would prefer single type case value, and report errors at startup - it is easier to check and optimize. It is better to use a transformation to convert the value to a specific type (e.g., {s.int}).
I mean, use transformation or equivalent to the variable used in 'switch(var)'.
Cheers, Daniel
Cheers, Daniel
We also check for a correct type of an integer in a mixed expression, e.g. if its a valid int value. I don't think that we convert them implicitly, as many pseudo-variables hold internally both a string and a integer value, so mixed expression will work just as intended in most cases.
Cheers,
Henning
sr-dev mailing list sr-dev@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
On 20-02 14:25, Andrei Pelinescu-Onciul wrote:
On Feb 20, 2009 at 14:03, Jan Janak jan@iptel.org wrote:
On 20-02 12:22, Andrei Pelinescu-Onciul wrote:
On Feb 20, 2009 at 11:15, Daniel-Constantin Mierla miconda@gmail.com wrote:
Hello Andrei,
On 02/20/2009 12:50 AM, Andrei Pelinescu-Onciul wrote:
[...]
script parsing: string switch support
that's great, thanks. From the next example, to understand the the case can take expression that evaluates to static strings or integers?
Yes. There are the following restriction:
- case labels must be static (no vars allowed)
- in the same switch you can have only one type of case labels: strings or integers (1)
- the first case label sets the required type for all the others
(so if your first case label is a string => all the other must be strings, if it's an integer all the other must be integers).
(1) - could be changed in some cases (e.g. string case with some int label allowed, which could be automatically converted to string), but I think it would too confusing and I disallowed it (in general having mixed types in a switch() are 99% an error).
I would suggest to convert numbers to strings in this case automatically. For most people things get more confusing with the increasing amount of details they have to remember about the configuration language.
This would only make sense if we use match() for strings and switch() for ints. Otherwise it would be too confusing. Anyway I don't think the amount of details of the configuration language is ever a problem, as long as one gets meaningful error messages when checking the config (and before ser startup). The other approaches trade-off less config details for guessing what the user intended, which IMO is much more dangerous. Is much better to get meaningful errors when running ser -cf ... , then getting unexpected behaviour at runtime (a very good example for this are typed variables vs. untyped ones or operators that try to guess the type and assume the user made the right choice).
OK, so if the script writer writes something like:
switch(@from.uri.user) { case "abc": ... case 100: ... case "foo" .. }
This is obviously a string based switch. What would you want to do with the second (integer) case? Report an error? Or convert it to string, making it equivalent to:
switch($foo) { case "abc": ... case "1": ... case "foo" .. }
This is the case we are talking about, right?
Jan.
Jan Janak writes:
OK, so if the script writer writes something like:
switch(@from.uri.user) { case "abc": ... case 100: ... case "foo" .. }
i my opinion it is unnecessary to allow such a mix of case label types. reporting an error is an appropriate thing to do.
-- juha
On 23-02 21:19, Juha Heinanen wrote:
Jan Janak writes:
OK, so if the script writer writes something like:
switch(@from.uri.user) { case "abc": ... case 100: ... case "foo" .. }
i my opinion it is unnecessary to allow such a mix of case label types. reporting an error is an appropriate thing to do.
Yeah, I admit that I might have been wrong, reporting an error seems appropriate. Andrei's last reply on this thread convinced me.
Jan.
On 20-02 14:25, Andrei Pelinescu-Onciul wrote:
On Feb 20, 2009 at 14:03, Jan Janak jan@iptel.org wrote:
On 20-02 12:22, Andrei Pelinescu-Onciul wrote:
On Feb 20, 2009 at 11:15, Daniel-Constantin Mierla miconda@gmail.com wrote:
Hello Andrei,
On 02/20/2009 12:50 AM, Andrei Pelinescu-Onciul wrote:
[...]
script parsing: string switch support
that's great, thanks. From the next example, to understand the the case can take expression that evaluates to static strings or integers?
Yes. There are the following restriction:
- case labels must be static (no vars allowed)
- in the same switch you can have only one type of case labels: strings or integers (1)
- the first case label sets the required type for all the others
(so if your first case label is a string => all the other must be strings, if it's an integer all the other must be integers).
(1) - could be changed in some cases (e.g. string case with some int label allowed, which could be automatically converted to string), but I think it would too confusing and I disallowed it (in general having mixed types in a switch() are 99% an error).
I would suggest to convert numbers to strings in this case automatically. For most people things get more confusing with the increasing amount of details they have to remember about the configuration language.
This would only make sense if we use match() for strings and switch() for ints. Otherwise it would be too confusing.
I like the idea of using match for strings and switch for integers, somehow using match for strings seams more logical to me, but I realize that this is just a personal preference.
Jan.
On 02/20/2009 01:22 PM, Andrei Pelinescu-Onciul wrote:
On Feb 20, 2009 at 11:15, Daniel-Constantin Mierla miconda@gmail.com wrote:
Hello Andrei,
On 02/20/2009 12:50 AM, Andrei Pelinescu-Onciul wrote:
[...]
script parsing: string switch support
that's great, thanks. From the next example, to understand the the case can take expression that evaluates to static strings or integers?
Yes. There are the following restriction:
- case labels must be static (no vars allowed)
- in the same switch you can have only one type of case labels: strings or integers (1)
- the first case label sets the required type for all the others
(so if your first case label is a string => all the other must be strings, if it's an integer all the other must be integers).
ok.
(1) - could be changed in some cases (e.g. string case with some int label allowed, which could be automatically converted to string), but I think it would too confusing and I disallowed it (in general having mixed types in a switch() are 99% an error).
I still think that using a different switch() name for strings will be less confusing (e.g. switch() for integers and match() for strings).
I prefer single type case value instead of mixed (as it is in kamailio now, but somehow useless and confusing, I doubt someone is using it), but not two different statements. I think switch as it is now is just fine.
Any opinion on how to differentiate regular expressions from strings? Right now a '/' in front means a regular expression (but there's no way to specify case insensitive match for example).
What about '~' which is the one used in IF.
Now, with while and switch in there I can work to get most of my configs working with sip-router.
Warning: the while works only with integers :-)
Do you mean that the expression has to evaluate to int? This has to be relaxed for strings and NULL for PVs. I will have a look latter.
Cheers, Daniel
Andrei
sr-dev mailing list sr-dev@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
Andrei Pelinescu-Onciul writes:
There are the following restriction:
- case labels must be static (no vars allowed)
- in the same switch you can have only one type of case labels: strings or integers (1)
- the first case label sets the required type for all the others
(so if your first case label is a string => all the other must be strings, if it's an integer all the other must be integers).
andrei,
thanks for the above implementation. the restrictions are fine with me,
-- juha