Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / nettle / sexp-format.c
blob93d1fd988a696f4cb9a812cb2a72da5396b59230
1 /* sexp-format.c
3 * Writing s-expressions.
4 */
6 /* nettle, low-level cryptographics library
8 * Copyright (C) 2002 Niels Möller
9 *
10 * The nettle library is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or (at your
13 * option) any later version.
15 * The nettle library is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with the nettle library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23 * MA 02111-1301, USA.
26 #if HAVE_CONFIG_H
27 # include "config.h"
28 #endif
30 #include <assert.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
36 #include "sexp.h"
37 #include "buffer.h"
39 #include "bignum.h"
41 static unsigned
42 format_prefix(struct nettle_buffer *buffer,
43 unsigned length)
45 unsigned digit = 1;
46 unsigned prefix_length = 1;
48 for (;;)
50 unsigned next = digit * 10;
51 if (next > length)
52 break;
54 prefix_length++;
55 digit = next;
58 if (buffer)
60 for (; digit; length %= digit, digit /= 10)
61 if (!NETTLE_BUFFER_PUTC(buffer, '0' + length / digit))
62 return 0;
64 if (!NETTLE_BUFFER_PUTC(buffer, ':'))
65 return 0;
68 return prefix_length + 1;
71 static unsigned
72 format_string(struct nettle_buffer *buffer,
73 unsigned length, const uint8_t *s)
75 unsigned prefix_length = format_prefix(buffer, length);
76 if (!prefix_length)
77 return 0;
79 if (buffer && !nettle_buffer_write(buffer, length, s))
80 return 0;
82 return prefix_length + length;
85 unsigned
86 sexp_vformat(struct nettle_buffer *buffer, const char *format, va_list args)
88 unsigned nesting = 0;
89 unsigned done = 0;
91 for (;;)
92 switch (*format++)
94 default:
96 const char *start = format - 1;
97 unsigned length = 1 + strcspn(format, "()% \t");
98 unsigned output_length = format_string(buffer, length, start);
99 if (!output_length)
100 return 0;
102 done += output_length;
103 format = start + length;
105 break;
107 case ' ': case '\t':
108 break;
110 case '\0':
111 assert(!nesting);
113 return done;
115 case '(':
116 if (buffer && !NETTLE_BUFFER_PUTC(buffer, '('))
117 return 0;
119 done++;
120 nesting++;
121 break;
123 case ')':
124 assert (nesting);
125 if (buffer && !NETTLE_BUFFER_PUTC(buffer, ')'))
126 return 0;
128 done++;
129 nesting--;
130 break;
132 case '%':
134 int nul_flag = 0;
136 if (*format == '0')
138 format++;
139 nul_flag = 1;
141 switch (*format++)
143 default:
144 abort();
146 case '(':
147 case ')':
148 /* Allow unbalanced parenthesis */
149 if (buffer && !NETTLE_BUFFER_PUTC(buffer, format[-1]))
150 return 0;
151 done++;
152 break;
154 case 's':
156 const char *s;
157 unsigned length;
158 unsigned output_length;
160 if (nul_flag)
162 s = va_arg(args, const char *);
163 length = strlen(s);
165 else
167 length = va_arg(args, unsigned);
168 s = va_arg(args, const char *);
171 output_length = format_string(buffer, length, s);
172 if (!output_length)
173 return 0;
175 done += output_length;
176 break;
178 case 't':
180 const char *s;
181 unsigned length;
182 unsigned output_length;
184 if (nul_flag)
186 s = va_arg(args, const char *);
187 if (!s)
188 break;
190 length = strlen(s);
192 else
194 length = va_arg(args, unsigned);
195 s = va_arg(args, const char *);
196 if (!s)
197 break;
200 if (buffer && !NETTLE_BUFFER_PUTC(buffer, '['))
201 return 0;
202 done++;
204 output_length = format_string(buffer, length, s);
206 if (!output_length)
207 return 0;
209 done += output_length;
211 if (buffer && !NETTLE_BUFFER_PUTC(buffer, ']'))
212 return 0;
213 done++;
215 break;
218 case 'l':
220 const char *s;
221 unsigned length;
223 if (nul_flag)
225 s = va_arg(args, const char *);
226 length = strlen(s);
228 else
230 length = va_arg(args, unsigned);
231 s = va_arg(args, const char *);
234 if (buffer && !nettle_buffer_write(buffer, length, s))
235 return 0;
237 done += length;
238 break;
240 case 'i':
242 uint32_t x = va_arg(args, uint32_t);
243 unsigned length;
245 if (x < 0x80)
246 length = 1;
247 else if (x < 0x8000L)
248 length = 2;
249 else if (x < 0x800000L)
250 length = 3;
251 else if (x < 0x80000000L)
252 length = 4;
253 else
254 length = 5;
256 if (buffer && !(NETTLE_BUFFER_PUTC(buffer, '0' + length)
257 && NETTLE_BUFFER_PUTC(buffer, ':')))
258 return 0;
260 done += (2 + length);
262 if (buffer)
263 switch(length)
265 case 5:
266 /* Leading byte needed for the sign. */
267 if (!NETTLE_BUFFER_PUTC(buffer, 0))
268 return 0;
269 /* Fall through */
270 case 4:
271 if (!NETTLE_BUFFER_PUTC(buffer, x >> 24))
272 return 0;
273 /* Fall through */
274 case 3:
275 if (!NETTLE_BUFFER_PUTC(buffer, (x >> 16) & 0xff))
276 return 0;
277 /* Fall through */
278 case 2:
279 if (!NETTLE_BUFFER_PUTC(buffer, (x >> 8) & 0xff))
280 return 0;
281 /* Fall through */
282 case 1:
283 if (!NETTLE_BUFFER_PUTC(buffer, x & 0xff))
284 return 0;
285 break;
286 default:
287 abort();
289 break;
291 case 'b':
293 const MP_INT *n = va_arg(args, const MP_INT *);
294 unsigned length;
295 unsigned prefix_length;
297 length = nettle_mpz_sizeinbase_256_s(n);
298 prefix_length = format_prefix(buffer, length);
299 if (!prefix_length)
300 return 0;
302 done += prefix_length;
304 if (buffer)
306 uint8_t *space = nettle_buffer_space(buffer, length);
307 if (!space)
308 return 0;
310 nettle_mpz_get_str_256(length, space, n);
313 done += length;
315 break;
322 unsigned
323 sexp_format(struct nettle_buffer *buffer, const char *format, ...)
325 va_list args;
326 unsigned done;
328 va_start(args, format);
329 done = sexp_vformat(buffer, format, args);
330 va_end(args);
332 return done;