Asterisk - The Open Source Telephony Project GIT-master-f36a736
func_sprintf.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2005-2006, Digium, Inc.
5 * Portions Copyright (C) 2005, Tilghman Lesher. All rights reserved.
6 * Portions Copyright (C) 2005, Anthony Minessale II
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*! \file
20 *
21 * \brief String manipulation dialplan functions
22 *
23 * \author Tilghman Lesher
24 * \author Anthony Minessale II
25 * \ingroup functions
26 */
27
28/*** MODULEINFO
29 <support_level>core</support_level>
30 ***/
31
32#include "asterisk.h"
33
34#include <ctype.h>
35
36#include "asterisk/module.h"
37#include "asterisk/channel.h"
38#include "asterisk/pbx.h"
39#include "asterisk/utils.h"
40#include "asterisk/app.h"
41
43
44/*** DOCUMENTATION
45 <function name="SPRINTF" language="en_US">
46 <synopsis>
47 Format a variable according to a format string.
48 </synopsis>
49 <syntax>
50 <parameter name="format" required="true" />
51 <parameter name="arg1" required="true" />
52 <parameter name="arg2" multiple="true" />
53 <parameter name="argN" />
54 </syntax>
55 <description>
56 <para>Parses the format string specified and returns a string matching
57 that format. Supports most options found in <emphasis>sprintf(3)</emphasis>.
58 Returns a shortened string if a format specifier is not recognized.</para>
59 </description>
60 <see-also>
61 <ref type="manpage">sprintf(3)</ref>
62 </see-also>
63 </function>
64 ***/
65static int acf_sprintf(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
66{
67#define SPRINTF_FLAG 0
68#define SPRINTF_WIDTH 1
69#define SPRINTF_PRECISION 2
70#define SPRINTF_LENGTH 3
71#define SPRINTF_CONVERSION 4
72 int i, state = -1, argcount = 0;
73 char *formatstart = NULL, *bufptr = buf;
74 char formatbuf[256] = "";
75 int tmpi;
76 double tmpd;
78 AST_APP_ARG(format);
79 AST_APP_ARG(var)[100];
80 );
81
82 AST_STANDARD_APP_ARGS(arg, data);
83
84 /* Scan the format, converting each argument into the requisite format type. */
85 for (i = 0; arg.format[i]; i++) {
86 switch (state) {
87 case SPRINTF_FLAG:
88 if (strchr("#0- +'I", arg.format[i]))
89 break;
91 case SPRINTF_WIDTH:
92 if (arg.format[i] >= '0' && arg.format[i] <= '9')
93 break;
94
95 /* Next character must be a period to go into a precision */
96 if (arg.format[i] == '.') {
98 } else {
100 i--;
101 }
102 break;
104 if (arg.format[i] >= '0' && arg.format[i] <= '9')
105 break;
107 case SPRINTF_LENGTH:
108 if (strchr("hl", arg.format[i])) {
109 if (arg.format[i + 1] == arg.format[i])
110 i++;
112 break;
113 } else if (strchr("Lqjzt", arg.format[i])) {
115 break;
116 }
119 if (strchr("diouxXc", arg.format[i])) {
120 /* Integer */
121
122 /* Isolate this format alone */
123 ast_copy_string(formatbuf, formatstart, sizeof(formatbuf));
124 formatbuf[&arg.format[i] - formatstart + 1] = '\0';
125
126 /* Convert the argument into the required type */
127 if (arg.var[argcount]) {
128 if (sscanf(arg.var[argcount++], "%30d", &tmpi) != 1) {
129 ast_log(LOG_ERROR, "Argument '%s' is not an integer number for format '%s'\n", arg.var[argcount - 1], formatbuf);
130 goto sprintf_fail;
131 }
132 } else {
133 ast_log(LOG_ERROR, "SPRINTF() has more format specifiers than arguments!\n");
134 goto sprintf_fail;
135 }
136
137 /* Format the argument */
138 snprintf(bufptr, buf + len - bufptr, formatbuf, tmpi);
139
140 /* Update the position of the next parameter to print */
141 bufptr = strchr(buf, '\0');
142 } else if (strchr("eEfFgGaA", arg.format[i])) {
143 /* Double */
144
145 /* Isolate this format alone */
146 ast_copy_string(formatbuf, formatstart, sizeof(formatbuf));
147 formatbuf[&arg.format[i] - formatstart + 1] = '\0';
148
149 /* Convert the argument into the required type */
150 if (arg.var[argcount]) {
151 if (sscanf(arg.var[argcount++], "%30lf", &tmpd) != 1) {
152 ast_log(LOG_ERROR, "Argument '%s' is not a floating point number for format '%s'\n", arg.var[argcount - 1], formatbuf);
153 goto sprintf_fail;
154 }
155 } else {
156 ast_log(LOG_ERROR, "SPRINTF() has more format specifiers than arguments!\n");
157 goto sprintf_fail;
158 }
159
160 /* Format the argument */
161 snprintf(bufptr, buf + len - bufptr, formatbuf, tmpd);
162
163 /* Update the position of the next parameter to print */
164 bufptr = strchr(buf, '\0');
165 } else if (arg.format[i] == 's') {
166 /* String */
167
168 /* Isolate this format alone */
169 ast_copy_string(formatbuf, formatstart, sizeof(formatbuf));
170 formatbuf[&arg.format[i] - formatstart + 1] = '\0';
171
172 /* Format the argument */
173 snprintf(bufptr, buf + len - bufptr, formatbuf, arg.var[argcount++]);
174
175 /* Update the position of the next parameter to print */
176 bufptr = strchr(buf, '\0');
177 } else if (arg.format[i] == '%') {
178 /* Literal data to copy */
179 *bufptr++ = arg.format[i];
180 } else {
181 /* Not supported */
182
183 /* Isolate this format alone */
184 ast_copy_string(formatbuf, formatstart, sizeof(formatbuf));
185 formatbuf[&arg.format[i] - formatstart + 1] = '\0';
186
187 ast_log(LOG_ERROR, "Format type not supported: '%s' with argument '%s'\n", formatbuf, arg.var[argcount++]);
188 goto sprintf_fail;
189 }
190 state = -1;
191 break;
192 default:
193 if (arg.format[i] == '%') {
195 formatstart = &arg.format[i];
196 break;
197 } else {
198 /* Literal data to copy */
199 *bufptr++ = arg.format[i];
200 }
201 }
202 }
203 *bufptr = '\0';
204 return 0;
205sprintf_fail:
206 return -1;
207}
208
210 .name = "SPRINTF",
211 .read = acf_sprintf,
212};
213
214static int unload_module(void)
215{
216 int res = 0;
217
219
220 return res;
221}
222
223static int load_module(void)
224{
225 int res = 0;
226
228
229 return res;
230}
231
232AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SPRINTF dialplan function");
#define var
Definition: ast_expr2f.c:605
Asterisk main include file. File version handling, generic pbx functions.
#define ast_log
Definition: astobj2.c:42
General Asterisk PBX channel definitions.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static struct ast_threadstorage result_buf
Definition: func_sprintf.c:42
#define SPRINTF_CONVERSION
static int acf_sprintf(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_sprintf.c:65
#define SPRINTF_WIDTH
#define SPRINTF_LENGTH
static struct ast_custom_function sprintf_function
Definition: func_sprintf.c:209
#define SPRINTF_PRECISION
#define SPRINTF_FLAG
static int load_module(void)
Definition: func_sprintf.c:223
static int unload_module(void)
Definition: func_sprintf.c:214
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define LOG_ERROR
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:581
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Core PBX routines and definitions.
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
#define NULL
Definition: resample.c:96
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Main Channel structure associated with a channel.
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
const char * name
Definition: pbx.h:119
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Definition: threadstorage.h:86
Utility functions.