Asterisk - The Open Source Telephony Project  18.5.0
func_math.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2004 - 2006, Andy Powell
5  *
6  * Updated by Mark Spencer <[email protected]>
7  * Updated by Nir Simionovich <[email protected]>
8  * Updated by Naveen Albert <[email protected]>
9  *
10  * See http://www.asterisk.org for more information about
11  * the Asterisk project. Please do not directly contact
12  * any of the maintainers of this project for assistance;
13  * the project provides a web site, mailing lists and IRC
14  * channels for your use.
15  *
16  * This program is free software, distributed under the terms of
17  * the GNU General Public License Version 2. See the LICENSE file
18  * at the top of the source tree.
19  */
20 
21 /*! \file
22  *
23  * \brief Math related dialplan function
24  *
25  * \author Andy Powell
26  * \author Mark Spencer <[email protected]>
27  * \author Nir Simionovich <[email protected]>
28  * \author Naveen Albert <[email protected]>
29  *
30  * \ingroup functions
31  */
32 
33 /*** MODULEINFO
34  <support_level>core</support_level>
35  ***/
36 
37 #include "asterisk.h"
38 
39 #include <math.h>
40 
41 #include "asterisk/module.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/pbx.h"
44 #include "asterisk/utils.h"
45 #include "asterisk/conversions.h"
46 #include "asterisk/app.h"
47 #include "asterisk/config.h"
48 #include "asterisk/test.h"
49 
50 /*** DOCUMENTATION
51  <function name="MATH" language="en_US">
52  <synopsis>
53  Performs Mathematical Functions.
54  </synopsis>
55  <syntax>
56  <parameter name="expression" required="true">
57  <para>Is of the form:
58  <replaceable>number1</replaceable><replaceable>op</replaceable><replaceable>number2</replaceable>
59  where the possible values for <replaceable>op</replaceable>
60  are:</para>
61  <para>+,-,/,*,%,&lt;&lt;,&gt;&gt;,^,AND,OR,XOR,&lt;,&gt;,&lt;=,&gt;=,== (and behave as their C equivalents)</para>
62  </parameter>
63  <parameter name="type">
64  <para>Wanted type of result:</para>
65  <para>f, float - float(default)</para>
66  <para>i, int - integer</para>
67  <para>h, hex - hex</para>
68  <para>c, char - char</para>
69  </parameter>
70  </syntax>
71  <description>
72  <para>Performs mathematical functions based on two parameters and an operator. The returned
73  value type is <replaceable>type</replaceable></para>
74  <para>Example: Set(i=${MATH(123%16,int)}) - sets var i=11</para>
75  </description>
76  </function>
77  <function name="INC" language="en_US">
78  <synopsis>
79  Increments the value of a variable, while returning the updated value to the dialplan
80  </synopsis>
81  <syntax>
82  <parameter name="variable" required="true">
83  <para>
84  The variable name to be manipulated, without the braces.
85  </para>
86  </parameter>
87  </syntax>
88  <description>
89  <para>Increments the value of a variable, while returning the updated value to the dialplan</para>
90  <para>Example: INC(MyVAR) - Increments MyVar</para>
91  <para>Note: INC(${MyVAR}) - Is wrong, as INC expects the variable name, not its value</para>
92  </description>
93  </function>
94  <function name="DEC" language="en_US">
95  <synopsis>
96  Decrements the value of a variable, while returning the updated value to the dialplan
97  </synopsis>
98  <syntax>
99  <parameter name="variable" required="true">
100  <para>
101  The variable name to be manipulated, without the braces.
102  </para>
103  </parameter>
104  </syntax>
105  <description>
106  <para>Decrements the value of a variable, while returning the updated value to the dialplan</para>
107  <para>Example: DEC(MyVAR) - Decrements MyVar</para>
108  <para>Note: DEC(${MyVAR}) - Is wrong, as DEC expects the variable name, not its value</para>
109  </description>
110  </function>
111  <function name="MIN" language="en_US">
112  <synopsis>
113  Returns the minimum of two numbers.
114  </synopsis>
115  <syntax>
116  <parameter name="num1" />
117  <parameter name="num2" />
118  </syntax>
119  <description>
120  <para>Returns the minimum of two numbers <replaceable>num1</replaceable> and <replaceable>num2</replaceable>.</para>
121  <para>Example: Set(min=${MIN(7,4)});
122  Sets the min variable equal to 4.</para>
123  </description>
124  </function>
125  <function name="MAX" language="en_US">
126  <synopsis>
127  Returns the maximum of two numbers.
128  </synopsis>
129  <syntax>
130  <parameter name="num1" />
131  <parameter name="num2" />
132  </syntax>
133  <description>
134  <para>Returns the maximum of two numbers <replaceable>num1</replaceable> and <replaceable>num2</replaceable>.</para>
135  <para>Example: Set(max=${MAX(4,7)});
136  Sets the max variable equal to 7.</para>
137  </description>
138  </function>
139  <function name="ABS" language="en_US">
140  <synopsis>
141  Returns absolute value of a number.
142  </synopsis>
143  <syntax>
144  <parameter name="num" />
145  </syntax>
146  <description>
147  <para>Returns the absolute value of a number <replaceable>num</replaceable>.</para>
148  <para>Example: Set(absval=${ABS(-13)});
149  Sets the absval variable equal to 13.</para>
150  </description>
151  </function>
152  ***/
153 
171 };
172 
178 };
179 
180 static int math(struct ast_channel *chan, const char *cmd, char *parse,
181  char *buf, size_t len)
182 {
183  double fnum1;
184  double fnum2;
185  double ftmp = 0;
186  char *op;
187  int iaction = -1;
188  int type_of_result = FLOAT_RESULT;
189  char *mvalue1, *mvalue2 = NULL, *mtype_of_result;
190  int negvalue1 = 0;
192  AST_APP_ARG(argv0);
193  AST_APP_ARG(argv1);
194  );
195 
196  if (ast_strlen_zero(parse)) {
197  ast_log(LOG_WARNING, "Syntax: MATH(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
198  return -1;
199  }
200 
201  AST_STANDARD_APP_ARGS(args, parse);
202 
203  if (args.argc < 1) {
204  ast_log(LOG_WARNING, "Syntax: MATH(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
205  return -1;
206  }
207 
208  mvalue1 = args.argv0;
209 
210  if (mvalue1[0] == '-') {
211  negvalue1 = 1;
212  mvalue1++;
213  }
214 
215  if ((op = strchr(mvalue1, '*'))) {
216  iaction = MULTIPLYFUNCTION;
217  *op = '\0';
218  } else if ((op = strchr(mvalue1, '/'))) {
219  iaction = DIVIDEFUNCTION;
220  *op = '\0';
221  } else if ((op = strchr(mvalue1, '%'))) {
222  iaction = MODULUSFUNCTION;
223  *op = '\0';
224  } else if ((op = strchr(mvalue1, '^'))) {
225  iaction = POWFUNCTION;
226  *op = '\0';
227  } else if ((op = strstr(mvalue1, "AND"))) {
228  iaction = BITWISEANDFUNCTION;
229  *op = '\0';
230  op += 2;
231  } else if ((op = strstr(mvalue1, "XOR"))) {
232  iaction = BITWISEXORFUNCTION;
233  *op = '\0';
234  op += 2;
235  } else if ((op = strstr(mvalue1, "OR"))) {
236  iaction = BITWISEORFUNCTION;
237  *op = '\0';
238  ++op;
239  } else if ((op = strchr(mvalue1, '>'))) {
240  iaction = GTFUNCTION;
241  *op = '\0';
242  if (*(op + 1) == '=') {
243  iaction = GTEFUNCTION;
244  ++op;
245  } else if (*(op + 1) == '>') {
246  iaction = SHRIGHTFUNCTION;
247  ++op;
248  }
249  } else if ((op = strchr(mvalue1, '<'))) {
250  iaction = LTFUNCTION;
251  *op = '\0';
252  if (*(op + 1) == '=') {
253  iaction = LTEFUNCTION;
254  ++op;
255  } else if (*(op + 1) == '<') {
256  iaction = SHLEFTFUNCTION;
257  ++op;
258  }
259  } else if ((op = strchr(mvalue1, '='))) {
260  *op = '\0';
261  if (*(op + 1) == '=') {
262  iaction = EQFUNCTION;
263  ++op;
264  } else
265  op = NULL;
266  } else if ((op = strchr(mvalue1, '+'))) {
267  iaction = ADDFUNCTION;
268  *op = '\0';
269  } else if ((op = strchr(mvalue1, '-'))) { /* subtraction MUST always be last, in case we have a negative second number */
270  iaction = SUBTRACTFUNCTION;
271  *op = '\0';
272  }
273 
274  if (op)
275  mvalue2 = op + 1;
276 
277  /* detect wanted type of result */
278  mtype_of_result = args.argv1;
279  if (mtype_of_result) {
280  if (!strcasecmp(mtype_of_result, "float")
281  || !strcasecmp(mtype_of_result, "f"))
282  type_of_result = FLOAT_RESULT;
283  else if (!strcasecmp(mtype_of_result, "int")
284  || !strcasecmp(mtype_of_result, "i"))
285  type_of_result = INT_RESULT;
286  else if (!strcasecmp(mtype_of_result, "hex")
287  || !strcasecmp(mtype_of_result, "h"))
288  type_of_result = HEX_RESULT;
289  else if (!strcasecmp(mtype_of_result, "char")
290  || !strcasecmp(mtype_of_result, "c"))
291  type_of_result = CHAR_RESULT;
292  else {
293  ast_log(LOG_WARNING, "Unknown type of result requested '%s'.\n",
294  mtype_of_result);
295  return -1;
296  }
297  }
298 
299  if (!mvalue2) {
301  "Supply all the parameters - just this once, please\n");
302  return -1;
303  }
304 
305  if (sscanf(mvalue1, "%30lf", &fnum1) != 1) {
306  ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
307  return -1;
308  }
309 
310  if (sscanf(mvalue2, "%30lf", &fnum2) != 1) {
311  ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue2);
312  return -1;
313  }
314 
315  if (negvalue1)
316  fnum1 = 0 - fnum1;
317 
318  switch (iaction) {
319  case ADDFUNCTION:
320  ftmp = fnum1 + fnum2;
321  break;
322  case DIVIDEFUNCTION:
323  if (fnum2 <= 0)
324  ftmp = 0; /* can't do a divide by 0 */
325  else
326  ftmp = (fnum1 / fnum2);
327  break;
328  case MULTIPLYFUNCTION:
329  ftmp = (fnum1 * fnum2);
330  break;
331  case SUBTRACTFUNCTION:
332  ftmp = (fnum1 - fnum2);
333  break;
334  case MODULUSFUNCTION:
335  {
336  int inum1 = fnum1;
337  int inum2 = fnum2;
338 
339  if (inum2 == 0) {
340  ftmp = 0;
341  } else {
342  ftmp = (inum1 % inum2);
343  }
344 
345  break;
346  }
347  case POWFUNCTION:
348  ftmp = pow(fnum1, fnum2);
349  break;
350  case SHLEFTFUNCTION:
351  {
352  int inum1 = fnum1;
353  int inum2 = fnum2;
354 
355  ftmp = (inum1 << inum2);
356  break;
357  }
358  case SHRIGHTFUNCTION:
359  {
360  int inum1 = fnum1;
361  int inum2 = fnum2;
362 
363  ftmp = (inum1 >> inum2);
364  break;
365  }
366  case BITWISEANDFUNCTION:
367  {
368  int inum1 = fnum1;
369  int inum2 = fnum2;
370  ftmp = (inum1 & inum2);
371  break;
372  }
373  case BITWISEXORFUNCTION:
374  {
375  int inum1 = fnum1;
376  int inum2 = fnum2;
377  ftmp = (inum1 ^ inum2);
378  break;
379  }
380  case BITWISEORFUNCTION:
381  {
382  int inum1 = fnum1;
383  int inum2 = fnum2;
384  ftmp = (inum1 | inum2);
385  break;
386  }
387  case GTFUNCTION:
388  ast_copy_string(buf, (fnum1 > fnum2) ? "TRUE" : "FALSE", len);
389  break;
390  case LTFUNCTION:
391  ast_copy_string(buf, (fnum1 < fnum2) ? "TRUE" : "FALSE", len);
392  break;
393  case GTEFUNCTION:
394  ast_copy_string(buf, (fnum1 >= fnum2) ? "TRUE" : "FALSE", len);
395  break;
396  case LTEFUNCTION:
397  ast_copy_string(buf, (fnum1 <= fnum2) ? "TRUE" : "FALSE", len);
398  break;
399  case EQFUNCTION:
400  ast_copy_string(buf, (fnum1 == fnum2) ? "TRUE" : "FALSE", len);
401  break;
402  default:
404  "Something happened that neither of us should be proud of %d\n",
405  iaction);
406  return -1;
407  }
408 
409  if (iaction < GTFUNCTION || iaction > EQFUNCTION) {
410  if (type_of_result == FLOAT_RESULT)
411  snprintf(buf, len, "%f", ftmp);
412  else if (type_of_result == INT_RESULT)
413  snprintf(buf, len, "%i", (int) ftmp);
414  else if (type_of_result == HEX_RESULT)
415  snprintf(buf, len, "%x", (unsigned int) ftmp);
416  else if (type_of_result == CHAR_RESULT)
417  snprintf(buf, len, "%c", (unsigned char) ftmp);
418  }
419 
420  return 0;
421 }
422 
423 static int crement_function_read(struct ast_channel *chan, const char *cmd,
424  char *data, char *buf, size_t len)
425 {
426  int ret = -1;
427  int int_value = 0;
428  int modify_orig = 0;
429  const char *var;
430  char endchar = 0, returnvar[12]; /* If you need a variable longer than 11 digits - something is way wrong */
431 
432  if (ast_strlen_zero(data)) {
433  ast_log(LOG_WARNING, "Syntax: %s(<data>) - missing argument!\n", cmd);
434  return -1;
435  }
436 
437  if (!chan) {
438  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
439  return -1;
440  }
441 
442  ast_channel_lock(chan);
443 
444  if (!(var = pbx_builtin_getvar_helper(chan, data))) {
445  ast_log(LOG_NOTICE, "Failed to obtain variable %s, bailing out\n", data);
446  ast_channel_unlock(chan);
447  return -1;
448  }
449 
450  if (ast_strlen_zero(var)) {
451  ast_log(LOG_NOTICE, "Variable %s doesn't exist - are you sure you wrote it correctly?\n", data);
452  ast_channel_unlock(chan);
453  return -1;
454  }
455 
456  if (sscanf(var, "%30d%1c", &int_value, &endchar) == 0 || endchar != 0) {
457  ast_log(LOG_NOTICE, "The content of ${%s} is not a numeric value - bailing out!\n", data);
458  ast_channel_unlock(chan);
459  return -1;
460  }
461 
462  /* now we'll actually do something useful */
463  if (!strcasecmp(cmd, "INC")) { /* Increment variable */
464  int_value++;
465  modify_orig = 1;
466  } else if (!strcasecmp(cmd, "DEC")) { /* Decrement variable */
467  int_value--;
468  modify_orig = 1;
469  }
470 
471  if (snprintf(returnvar, sizeof(returnvar), "%d", int_value) > 0) {
472  pbx_builtin_setvar_helper(chan, data, returnvar);
473  if (modify_orig) {
474  ast_copy_string(buf, returnvar, len);
475  }
476  ret = 0;
477  } else {
478  pbx_builtin_setvar_helper(chan, data, "0");
479  if (modify_orig) {
480  ast_copy_string(buf, "0", len);
481  }
482  ast_log(LOG_NOTICE, "Variable %s refused to be %sREMENTED, setting value to 0", data, cmd);
483  ret = 0;
484  }
485 
486  ast_channel_unlock(chan);
487 
488  return ret;
489 }
490 
491 static int acf_min_exec(struct ast_channel *chan, const char *cmd,
492  char *parse, char *buffer, size_t buflen)
493 {
494  double num1, num2, response_num = 0;
496  AST_APP_ARG(num1);
497  AST_APP_ARG(num2);
498  );
499 
500  AST_STANDARD_APP_ARGS(args, parse);
501 
502  if (ast_strlen_zero(args.num1) && ast_strlen_zero(args.num2)) {
503  ast_log(LOG_ERROR, "Missing argument for number(s).");
504  return -1;
505  }
506 
507  if (ast_strlen_zero(args.num1)) {
508  response_num = -1; /* couldn't read num1 successfully */
509  } else if (sscanf(args.num1, "%30lf", &num1) != 1) {
510  ast_log(LOG_WARNING, "'%s' is not a valid number\n", args.num1);
511  return -1;
512  }
513 
514  if (ast_strlen_zero(args.num2)) {
515  num2 = num1; /* num1 must be a valid integer here */
516  } else if (sscanf(args.num2, "%30lf", &num2) != 1) {
517  ast_log(LOG_WARNING, "'%s' is not a valid number\n", args.num2);
518  return -1;
519  }
520 
521  if (response_num == -1) { /* could only read num2 */
522  response_num = num2;
523  } else {
524  response_num = (num1 > num2) ? num2 : num1;
525  }
526 
527  ast_debug(1, "%f is the minimum of [%f,%f]\n", response_num, num1, num2);
528  if ((int) response_num == response_num) {
529  snprintf(buffer, buflen, "%d", (int) response_num);
530  } else {
531  snprintf(buffer, buflen, "%f", response_num);
532  }
533 
534  return 0;
535 }
536 
537 static int acf_max_exec(struct ast_channel *chan, const char *cmd,
538  char *parse, char *buffer, size_t buflen)
539 {
540  double num1, num2, response_num = 0;
542  AST_APP_ARG(num1);
543  AST_APP_ARG(num2);
544  );
545 
546  AST_STANDARD_APP_ARGS(args, parse);
547 
548  if (ast_strlen_zero(args.num1) && ast_strlen_zero(args.num2)) {
549  ast_log(LOG_ERROR, "Missing argument for number(s).");
550  return -1;
551  }
552 
553  if (ast_strlen_zero(args.num1)) {
554  response_num = -1; /* couldn't read num1 successfully */
555  } else if (sscanf(args.num1, "%30lf", &num1) != 1) {
556  ast_log(LOG_WARNING, "'%s' is not a valid number\n", args.num1);
557  return -1;
558  }
559 
560  if (ast_strlen_zero(args.num2)) {
561  num2 = num1; /* num1 must be a valid integer here */
562  } else if (sscanf(args.num2, "%30lf", &num2) != 1) {
563  ast_log(LOG_WARNING, "'%s' is not a valid number\n", args.num2);
564  return -1;
565  }
566 
567  if (response_num == -1) { /* could only read num2 */
568  response_num = num2;
569  } else {
570  response_num = (num1 < num2) ? num2 : num1;
571  }
572 
573  ast_debug(1, "%f is the maximum of [%f,%f]\n", response_num, num1, num2);
574  if ((int) response_num == response_num) {
575  snprintf(buffer, buflen, "%d", (int) response_num);
576  } else {
577  snprintf(buffer, buflen, "%f", response_num);
578  }
579 
580  return 0;
581 }
582 
583 static int acf_abs_exec(struct ast_channel *chan, const char *cmd,
584  char *parse, char *buffer, size_t buflen)
585 {
586  double num1, response_num;
588  AST_APP_ARG(num1);
589  );
590 
591  AST_STANDARD_APP_ARGS(args, parse);
592 
593  if (ast_strlen_zero(args.num1) || sscanf(args.num1, "%30lf", &num1) != 1) {
594  ast_log(LOG_WARNING, "Bad or missing argument for number: %s", args.num1);
595  return -1;
596  }
597 
598  response_num = fabs(num1);
599  ast_debug(1, "%f is the absolute value of %f\n", response_num, num1);
600  if ((int) response_num == response_num) {
601  snprintf(buffer, buflen, "%d", (int) response_num);
602  } else {
603  snprintf(buffer, buflen, "%f", response_num);
604  }
605 
606  return 0;
607 }
608 
610  .name = "MATH",
611  .read = math
612 };
613 
615  .name = "INC",
616  .read = crement_function_read,
617 };
618 
620  .name = "DEC",
621  .read = crement_function_read,
622 };
623 
624 static struct ast_custom_function acf_min = {
625  .name = "MIN",
626  .read = acf_min_exec,
627  .read_max = 12,
628 };
629 
630 static struct ast_custom_function acf_max = {
631  .name = "MAX",
632  .read = acf_max_exec,
633  .read_max = 12,
634 };
635 
636 static struct ast_custom_function acf_abs = {
637  .name = "ABS",
638  .read = acf_abs_exec,
639  .read_max = 12,
640 };
641 
642 #ifdef TEST_FRAMEWORK
643 AST_TEST_DEFINE(test_MATH_function)
644 {
646  struct ast_str *expr, *result;
647 
648  switch (cmd) {
649  case TEST_INIT:
650  info->name = "test_MATH_function";
651  info->category = "/main/pbx/";
652  info->summary = "Test MATH function substitution";
653  info->description =
654  "Executes a series of variable substitutions using the MATH function and ensures that the expected results are received.";
655  return AST_TEST_NOT_RUN;
656  case TEST_EXECUTE:
657  break;
658  }
659 
660  ast_test_status_update(test, "Testing MATH() substitution ...\n");
661 
662  if (!(expr = ast_str_create(16))) {
663  return AST_TEST_FAIL;
664  }
665  if (!(result = ast_str_create(16))) {
666  ast_free(expr);
667  return AST_TEST_FAIL;
668  }
669 
670  ast_str_set(&expr, 0, "${MATH(170 AND 63,i)}");
672  if (strcmp(ast_str_buffer(result), "42") != 0) {
673  ast_test_status_update(test, "Expected result '42' not returned! ('%s')\n",
674  ast_str_buffer(result));
675  res = AST_TEST_FAIL;
676  }
677 
678  ast_str_set(&expr, 0, "${MATH(170AND63,i)}");
680  if (strcmp(ast_str_buffer(result), "42") != 0) {
681  ast_test_status_update(test, "Expected result '42' not returned! ('%s')\n",
682  ast_str_buffer(result));
683  res = AST_TEST_FAIL;
684  }
685 
686  ast_free(expr);
687  ast_free(result);
688 
689  return res;
690 }
691 #endif
692 
693 static int unload_module(void)
694 {
695  int res = 0;
696 
697  res |= ast_custom_function_unregister(&math_function);
698  res |= ast_custom_function_unregister(&increment_function);
699  res |= ast_custom_function_unregister(&decrement_function);
700  res |= ast_custom_function_unregister(&acf_min);
701  res |= ast_custom_function_unregister(&acf_max);
702  res |= ast_custom_function_unregister(&acf_abs);
703  AST_TEST_UNREGISTER(test_MATH_function);
704 
705  return res;
706 }
707 
708 static int load_module(void)
709 {
710  int res = 0;
711 
712  res |= ast_custom_function_register(&math_function);
713  res |= ast_custom_function_register(&increment_function);
714  res |= ast_custom_function_register(&decrement_function);
715  res |= ast_custom_function_register(&acf_min);
716  res |= ast_custom_function_register(&acf_max);
717  res |= ast_custom_function_register(&acf_abs);
718  AST_TEST_REGISTER(test_MATH_function);
719 
720  return res;
721 }
722 
723 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Mathematical dialplan function");
const char * name
Definition: pbx.h:119
static struct ast_custom_function math_function
Definition: func_math.c:609
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
static struct ast_custom_function acf_max
Definition: func_math.c:630
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_custom_function decrement_function
Definition: func_math.c:619
static int unload_module(void)
Definition: func_math.c:693
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
AST_TEST_DEFINE(test_MATH_function)
Definition: func_math.c:643
#define var
Definition: ast_expr2f.c:614
static struct ast_custom_function acf_abs
Definition: func_math.c:636
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
Test Framework API.
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
TypeOfResult
Definition: func_math.c:173
const char * args
#define NULL
Definition: resample.c:96
static struct ast_custom_function acf_min
Definition: func_math.c:624
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Utility functions.
#define ast_strlen_zero(foo)
Definition: strings.h:52
static int crement_function_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_math.c:423
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
Configuration File Parser.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static struct ast_custom_function increment_function
Definition: func_math.c:614
General Asterisk PBX channel definitions.
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
Conversion utility functions.
Core PBX routines and definitions.
#define LOG_ERROR
Definition: logger.h:285
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
TypeOfFunctions
Definition: func_math.c:154
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
def info(msg)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define LOG_NOTICE
Definition: logger.h:263
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define ast_free(a)
Definition: astmm.h:182
static int acf_min_exec(struct ast_channel *chan, const char *cmd, char *parse, char *buffer, size_t buflen)
Definition: func_math.c:491
static int math(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_math.c:180
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static PGresult * result
Definition: cel_pgsql.c:88
static int acf_abs_exec(struct ast_channel *chan, const char *cmd, char *parse, char *buffer, size_t buflen)
Definition: func_math.c:583
static int load_module(void)
Definition: func_math.c:708
static int acf_max_exec(struct ast_channel *chan, const char *cmd, char *parse, char *buffer, size_t buflen)
Definition: func_math.c:537
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508
ast_test_result_state
Definition: test.h:200
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
#define AST_APP_ARG(name)
Define an application argument.