README 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. Eval module
  2. ===========
  3. Author: tomas.mandys at iptel dot org
  4. The module implements expression evaluation in route script, i.e. enables
  5. e.g. addition, concatanation, value items etc. There are two basic types:
  6. integer and string. Operation are processed using values on stack and
  7. polish notation. Besides the stack there are also register that may be
  8. accessed by quick manner in run time, via select or stack manipulation functions,
  9. because they are fixed during fixup phase.
  10. Module parameters:
  11. -----------------
  12. declare_register: string;
  13. Declares one register, multiple declaration supported
  14. Example:
  15. modparam("eval", "declare_register", "ax");
  16. modparam("eval", "declare_register", "bx");
  17. modparam("eval", "declare_register", "cx");
  18. modparam("eval", "declare_register", "dx");
  19. xlbuf_size: int;
  20. Default: 4096
  21. Size of buffer for xlib formating.
  22. Module functions:
  23. ----------------
  24. location:
  25. Location for stack manipulation operation. Thare are supported int/str constant,
  26. AVP, register, xlib formatted string
  27. integers: any value (included string) that may be converted to int
  28. string: any string, prefix "s:" forces string even when is "integer"
  29. xlib: string prefixed by "x:"
  30. AVP: an AVP compliant string starting with "$"
  31. register: register name declared using "declare_register" and starting with "r:"
  32. function: get value from function, "f:<funcname>"
  33. Currently are supported following functions:
  34. time ... get time in seconds
  35. uuid ... get uuid using uuid library
  36. stackno ... get current stack size
  37. Example:
  38. "f:time"
  39. Note that result of any select may be used using xlib string, e.g. "x:%@eval.get[0]"
  40. stack_pos:
  41. Position on the stack. Values greater or equal than zero are counted from top, negative values counted
  42. from bottom, i.e. 0..topmost position, -1..bottommost position
  43. Example:
  44. Value Idx as or
  45. 3456 0 -5
  46. 5678 1 -4
  47. 87655 2 -3
  48. 76534 3 -2
  49. -1543 4 -1
  50. Stack manipulation functions return TRUE/FALSE if operation was succesfull or not. Every stack_pos/num may be
  51. evaluated in runtime using location (AVP, register, xlstr).
  52. eval_add(location[, stack_pos]);
  53. eval_push(location[, stack_pos]);
  54. Default: stack_pos: -1
  55. Add value bellow stack_pos item.
  56. Example:
  57. eval_push("1");
  58. eval_push("$a");
  59. eval_push("x:%ru", -2);
  60. $pos = 1;
  61. eval_push("ABC", "$pos");
  62. eval_insert(location[, stack_pos]);
  63. Default: stack_pos: 0
  64. Add value above stack_pos item.
  65. Example:
  66. eval_insert("s:1");
  67. eval_push("f:uuid");
  68. eval_push("f:time");
  69. eval_xchg(location[, stack_pos]);
  70. Default: stack_pos: 0
  71. Exchange values between stack and location. Note that only
  72. register location is allowed.
  73. eval_get(location[, stack_pos]);
  74. Default: stack_pos: 0
  75. Move value from stack to (writable) location, i.e. AVP, register.
  76. Note that enables assigning AVP value also as interger
  77. (vs. select that returns alway string)
  78. Example:
  79. eval_get("$avp", 2);
  80. eval_put(location[, stack_pos]);
  81. Default: stack_pos: 0
  82. Move value from location to stack.
  83. eval_add_value(location[, num]);
  84. Default: num: -1
  85. Split value (comma delimited items) and add to stack
  86. Example:
  87. eval_add_value("One,Two,Three,Four"); # add 4 items stack
  88. eval_insert_value(location[, num]);
  89. Default: num: 0
  90. Split value (comma delimited items) and insert to stack
  91. eval_pop(location[, stack_pos]);
  92. Default: stack_pos: 0
  93. Get value from writable location and remove it from the stack
  94. eval_remove([stack_pos[, num]]);
  95. Default: stack_pos: 0; num: 1
  96. Remove num items from the stack starting at stack_pos. If num is negative then stops removing (-num) element before bottom.
  97. Example:
  98. $pos = 1;
  99. $num = 3;
  100. eval_remove("$pos", "$num");
  101. eval_clear(what);
  102. Clear stack (if bit0 in what set) or registers (if bit1 in what set)
  103. eval_oper(operations[, stack_pos]);
  104. Default: stack_pos: 0
  105. Perform comma delimited operations relating to stack_pos, i.e. get n parameters (stack_pos, stack_pos+1, ...stack_pos+n-1),
  106. put result at stack_pos and remove params (stack_pos+1, ...stack_pos+n-1). When not enough params availble then
  107. false is returned, error logged and stack is in state in time of error (i.e. probably unpredictable).
  108. Operation may contain location (avp,xlib str,register) to evaluate function in runtime, i.e. indirect functions. Note
  109. that particular operation is evaluated, not complete string:
  110. $op1="abs"; $op2="/"; eval_oper("$op1,$op2,+,*"); # OK
  111. $op = "abs,/,+,*"; eval_oper("$op"); # BAD
  112. Example:
  113. eval_push("2");
  114. eval_push("3");
  115. eval_push("9");
  116. eval_oper("+,*"); # i.e. (2+3)*9 = 54
  117. eval_insert("100", 0);
  118. $op="-";
  119. eval_oper("$op"); # i.e. 100-54 = 64
  120. eval_while(route_no [, stack_pos])
  121. Default: stack_pos: 0
  122. Implements simple looping. Route_no is called while stack[stack_pos] is true, i.e.
  123. non empty integer non equal zero or non empty string.
  124. Loop is also interrupted if route_no returns value <= 0.
  125. Example:
  126. route[LOOP] {
  127. xplog("L_ERR", "%@eval.get[1] = %@eval.pop[2]\n");
  128. eval_oper("dec");
  129. eval_oper("inc", 1);
  130. }
  131. eval_push(3);
  132. eval_push(1);
  133. eval_push("One");
  134. eval_push("Two");
  135. eval_push("Three");
  136. eval_while("LOOP");
  137. eval_remove(0, 2);
  138. Example for mathematicians using ser as scientic calculator:
  139. route["FACTORIAL"] {
  140. if (@eval.get[0] == "-1") { # first loop ?
  141. xplog("L_ERR", "How much is factorial of %@eval.get[1] ? \n");
  142. eval_get("r:tmp", 1);
  143. eval_put("r:tmp");
  144. eval_oper("sgn");
  145. if (@eval.get[0] == "0" || @eval.reg.tmp == "1") { # zero is exception, one is optimization
  146. xplog("L_ERR", "1\n");
  147. eval_put(1);
  148. eval_remove(1);
  149. return -1;
  150. }
  151. else if (@eval.get[0] == "-1") { # negative x is nonsense
  152. xplog("L_ERR", "not defined\n");
  153. eval_remove(1);
  154. return -1;
  155. }
  156. # stack[0] is 1
  157. }
  158. eval_get("r:tmp", 1); # save x
  159. eval_oper("*"); # r *= x
  160. if (@eval.reg.tmp == "2") {
  161. xplog("L_ERR", "%@eval.get[0]\n");
  162. return -1;
  163. }
  164. eval_push("r:tmp");
  165. eval_oper("dec", 1); # x--
  166. }
  167. route{
  168. eval_push("-1"); # condition
  169. eval_push(0);
  170. eval_while("FACTORIAL");
  171. eval_remove();
  172. eval_push("-1"); # condition
  173. eval_push(1);
  174. eval_while("FACTORIAL");
  175. eval_remove();
  176. eval_push("-1"); # condition
  177. eval_push(-3);
  178. eval_while("FACTORIAL");
  179. eval_remove();
  180. eval_push("-1"); # condition
  181. eval_push(9);
  182. eval_while("FACTORIAL");
  183. eval_remove();
  184. Keen ser user will implement inverse hyperbolic tangens as homework.
  185. eval_while_stack(route_no [, stack_count])
  186. Default: stack_count: 0
  187. Implements simple looping. Route_no is called while number of stack item is
  188. greater than stack_count, resp. lower than abs(stack_count) if stack_count is negative.
  189. Loop is also interrupted if route_no returns value <= 0.
  190. Example:
  191. route[LOOP] {
  192. xplog("L_ERR", "%@eval.pop[0]\n");
  193. }
  194. eval_push("Three");
  195. eval_push("Two");
  196. eval_push("One");
  197. eval_push("GO!");
  198. eval_while_stack("LOOP");
  199. eval_dump();
  200. Dumps stack and registers to stderr. For debugging purposes.
  201. Selects:
  202. -------
  203. @eval.pop[stack_pos]
  204. Get value of stack item and remove it from the stack
  205. @eval.get[stack_pos]
  206. Get register value
  207. @eval.reg.REGNAME
  208. Return register value.
  209. Example:
  210. if (@eval.reg.ax == @eval.get[0]) {
  211. }
  212. Note that @eval.get and @eval.reg support select_any_uri and select_any_nameaddr
  213. @eval.uuid
  214. Generates uuid, obsolete use @sys.unique
  215. Operators/functions
  216. -------------------
  217. String <-> integer conversion is perfomed automatically.
  218. "+" ... additon, 2 (int) params
  219. "-" ... subtraction, 2 (int) params
  220. "*" ... multiplication, 2 (int) params
  221. "/" ... division, 2 (int) params
  222. "%" ... modulo, 2 (int) params
  223. "neg" ... negation, 1 (int) param
  224. "abs" ... absolute value, 1 (int) param
  225. "sgn" ... signum, 1 (int) param
  226. "dec" ... decrement, 1 (int) param
  227. "inc" ... increment, 1 (int) param
  228. "&" ... bitand, 2 (int) params
  229. "|" ... bitor, 2 (int) params
  230. "^" ... bitxor, 2 (int) params
  231. "~" ... bitnot, 1 (int) param
  232. "&&" ... and, 2 (int) params
  233. "||" ... or, 2 (int) params
  234. "!" ... not, 1 (int) params
  235. "==" ... equal, 2 (any) params
  236. "!=" ... non equal, 2 (any) params
  237. ">" ... greater, 2 (any) params
  238. ">=" ... greater or equal, 2 (any) params
  239. "<" ... lower, 2 (any) params
  240. "<=" ... lower or equal, 2 (any) params
  241. "concat" ... string concatanation, 2 (str) params
  242. "substr" ... substring, (str) param, (int) position, (int) length
  243. get substring
  244. If start is non-negative, the returned string will start at the start'th position in string, counting from zero. For instance, in the string 'abcdef', the character at position 0 is 'a', the character at position 2 is 'c', and so forth. If start is negative, the returned string will start at the start'th character from the end of string.
  245. If length is given and is positive, the string returned will contain at most length characters beginning from start (depending on the length of string). If string is less than or equal to start characters long, empty string is returned.
  246. If length is given and is negative, then that many characters will be omitted from the end of string (after the start position has been calculated when a start is negative). If start denotes a position beyond this truncation, an empty string will be returned.
  247. "strdel" ... delete substring, (str) param, (int) position, (int) length
  248. see substr
  249. "strlen" ... str length, (str) param
  250. "strstr" ... substring position, (str) string, (str) needle
  251. Return position of needle in string, -1 if not found
  252. "strupper" ... upcase, (str) str
  253. "strlower" ... locase, (str) str
  254. "(int)" ... cast item as integer
  255. "(str)" ... cast item as string
  256. Value oparation:
  257. working with comma delimited list of values, e.g. Record-route, route, etc.
  258. "valat" ... get value at index, (str) values, (int) idx
  259. Get values[idx], positive/negative logic similar to stack manipulation
  260. "valuris" ... get values in "normalized" form (uri only), (str) values
  261. "valrev" ... get values in reversal order, (str) values
  262. "subval" ... get subvalues, (str) values, (idx) index, (len) length (... see substr)
  263. "strvalat" ... (str) values, (str) needle, get index of string in value (-1 if string does not exist)
  264. "valcount" ... get number of items
  265. "geturi" ... get uri part, "<", ">" are stripped, (str) addr
  266. "valconcat" ... concatenate n stack items to value, n<=0 returns empty string, (int) n, (str) v1 ... (str) vn