]> git.ipfire.org Git - people/ms/strongswan.git/blob - src/libfreeswan/ttodata.c
_copyright: Replicate copyright text here instead of calling libfreeswan.
[people/ms/strongswan.git] / src / libfreeswan / ttodata.c
1 /*
2 * convert from text form of arbitrary data (e.g., keys) to binary
3 * Copyright (C) 2000 Henry Spencer.
4 *
5 * This library is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU Library General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
9 *
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 * License for more details.
14 */
15 #include "internal.h"
16 #include "freeswan.h"
17
18 /* converters and misc */
19 static int unhex(const char *, char *, size_t);
20 static int unb64(const char *, char *, size_t);
21 static int untext(const char *, char *, size_t);
22 static const char *badch(const char *, int, char *, size_t);
23
24 /* internal error codes for converters */
25 #define SHORT (-2) /* internal buffer too short */
26 #define BADPAD (-3) /* bad base64 padding */
27 #define BADCH0 (-4) /* invalid character 0 */
28 #define BADCH1 (-5) /* invalid character 1 */
29 #define BADCH2 (-6) /* invalid character 2 */
30 #define BADCH3 (-7) /* invalid character 3 */
31 #define BADOFF(code) (BADCH0-(code))
32
33 /*
34 - ttodatav - convert text to data, with verbose error reports
35 * If some of this looks slightly odd, it's because it has changed
36 * repeatedly (from the original atodata()) without a major rewrite.
37 */
38 const char * /* NULL on success, else literal or errp */
39 ttodatav(src, srclen, base, dst, dstlen, lenp, errp, errlen, flags)
40 const char *src;
41 size_t srclen; /* 0 means apply strlen() */
42 int base; /* 0 means figure it out */
43 char *dst; /* need not be valid if dstlen is 0 */
44 size_t dstlen;
45 size_t *lenp; /* where to record length (NULL is nowhere) */
46 char *errp; /* error buffer */
47 size_t errlen;
48 unsigned int flags;
49 {
50 size_t ingroup; /* number of input bytes converted at once */
51 char buf[4]; /* output from conversion */
52 int nbytes; /* size of output */
53 int (*decode)(const char *, char *, size_t);
54 char *stop;
55 int ndone;
56 int i;
57 int underscoreok;
58 int skipSpace = 0;
59
60 if (srclen == 0)
61 srclen = strlen(src);
62 if (dstlen == 0)
63 dst = buf; /* point it somewhere valid */
64 stop = dst + dstlen;
65
66 if (base == 0) {
67 if (srclen < 2)
68 return "input too short to be valid";
69 if (*src++ != '0')
70 return "input does not begin with format prefix";
71 switch (*src++) {
72 case 'x':
73 case 'X':
74 base = 16;
75 break;
76 case 's':
77 case 'S':
78 base = 64;
79 break;
80 case 't':
81 case 'T':
82 base = 256;
83 break;
84 default:
85 return "unknown format prefix";
86 }
87 srclen -= 2;
88 }
89 switch (base) {
90 case 16:
91 decode = unhex;
92 underscoreok = 1;
93 ingroup = 2;
94 break;
95 case 64:
96 decode = unb64;
97 underscoreok = 0;
98 ingroup = 4;
99 if(flags & TTODATAV_IGNORESPACE) {
100 skipSpace = 1;
101 }
102 break;
103
104 case 256:
105 decode = untext;
106 ingroup = 1;
107 underscoreok = 0;
108 break;
109 default:
110 return "unknown base";
111 }
112
113 /* proceed */
114 ndone = 0;
115 while (srclen > 0) {
116 char stage[4]; /* staging area for group */
117 size_t sl = 0;
118
119 /* Grab ingroup characters into stage,
120 * squeezing out blanks if we are supposed to ignore them.
121 */
122 for (sl = 0; sl < ingroup; src++, srclen--) {
123 if (srclen == 0)
124 return "input ends in mid-byte, perhaps truncated";
125 else if (!(skipSpace && (*src == ' ' || *src == '\t')))
126 stage[sl++] = *src;
127 }
128
129 nbytes = (*decode)(stage, buf, sizeof(buf));
130 switch (nbytes) {
131 case BADCH0:
132 case BADCH1:
133 case BADCH2:
134 case BADCH3:
135 return badch(stage, nbytes, errp, errlen);
136 case SHORT:
137 return "internal buffer too short (\"can't happen\")";
138 case BADPAD:
139 return "bad (non-zero) padding at end of base64 input";
140 }
141 if (nbytes <= 0)
142 return "unknown internal error";
143 for (i = 0; i < nbytes; i++) {
144 if (dst < stop)
145 *dst++ = buf[i];
146 ndone++;
147 }
148 while (srclen >= 1 && skipSpace && (*src == ' ' || *src == '\t')){
149 src++;
150 srclen--;
151 }
152 if (underscoreok && srclen > 1 && *src == '_') {
153 /* srclen > 1 means not last character */
154 src++;
155 srclen--;
156 }
157 }
158
159 if (ndone == 0)
160 return "no data bytes specified by input";
161 if (lenp != NULL)
162 *lenp = ndone;
163 return NULL;
164 }
165
166 /*
167 - ttodata - convert text to data
168 */
169 const char * /* NULL on success, else literal */
170 ttodata(src, srclen, base, dst, dstlen, lenp)
171 const char *src;
172 size_t srclen; /* 0 means apply strlen() */
173 int base; /* 0 means figure it out */
174 char *dst; /* need not be valid if dstlen is 0 */
175 size_t dstlen;
176 size_t *lenp; /* where to record length (NULL is nowhere) */
177 {
178 return ttodatav(src, srclen, base, dst, dstlen, lenp, (char *)NULL,
179 (size_t)0, TTODATAV_SPACECOUNTS);
180 }
181
182 /*
183 - atodata - convert ASCII to data
184 * backward-compatibility interface
185 */
186 size_t /* 0 for failure, true length for success */
187 atodata(src, srclen, dst, dstlen)
188 const char *src;
189 size_t srclen;
190 char *dst;
191 size_t dstlen;
192 {
193 size_t len;
194 const char *err;
195
196 err = ttodata(src, srclen, 0, dst, dstlen, &len);
197 if (err != NULL)
198 return 0;
199 return len;
200 }
201
202 /*
203 - atobytes - convert ASCII to data bytes
204 * another backward-compatibility interface
205 */
206 const char *
207 atobytes(src, srclen, dst, dstlen, lenp)
208 const char *src;
209 size_t srclen;
210 char *dst;
211 size_t dstlen;
212 size_t *lenp;
213 {
214 return ttodata(src, srclen, 0, dst, dstlen, lenp);
215 }
216
217 /*
218 - unhex - convert two ASCII hex digits to byte
219 */
220 static int /* number of result bytes, or error code */
221 unhex(src, dst, dstlen)
222 const char *src; /* known to be full length */
223 char *dst;
224 size_t dstlen; /* not large enough is a failure */
225 {
226 char *p;
227 unsigned byte;
228 static char hex[] = "0123456789abcdef";
229
230 if (dstlen < 1)
231 return SHORT;
232
233 p = strchr(hex, *src);
234 if (p == NULL)
235 p = strchr(hex, tolower(*src));
236 if (p == NULL)
237 return BADCH0;
238 byte = (p - hex) << 4;
239 src++;
240
241 p = strchr(hex, *src);
242 if (p == NULL)
243 p = strchr(hex, tolower(*src));
244 if (p == NULL)
245 return BADCH1;
246 byte |= (p - hex);
247
248 *dst = byte;
249 return 1;
250 }
251
252 /*
253 - unb64 - convert four ASCII base64 digits to three bytes
254 * Note that a base64 digit group is padded out with '=' if it represents
255 * less than three bytes: one byte is dd==, two is ddd=, three is dddd.
256 */
257 static int /* number of result bytes, or error code */
258 unb64(src, dst, dstlen)
259 const char *src; /* known to be full length */
260 char *dst;
261 size_t dstlen;
262 {
263 char *p;
264 unsigned byte1;
265 unsigned byte2;
266 static char base64[] =
267 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
268
269 if (dstlen < 3)
270 return SHORT;
271
272 p = strchr(base64, *src++);
273
274 if (p == NULL)
275 return BADCH0;
276 byte1 = (p - base64) << 2; /* first six bits */
277
278 p = strchr(base64, *src++);
279 if (p == NULL) {
280 return BADCH1;
281 }
282
283 byte2 = p - base64; /* next six: two plus four */
284 *dst++ = byte1 | (byte2 >> 4);
285 byte1 = (byte2 & 0xf) << 4;
286
287 p = strchr(base64, *src++);
288 if (p == NULL) {
289 if (*(src-1) == '=' && *src == '=') {
290 if (byte1 != 0) /* bad padding */
291 return BADPAD;
292 return 1;
293 }
294 return BADCH2;
295 }
296
297 byte2 = p - base64; /* next six: four plus two */
298 *dst++ = byte1 | (byte2 >> 2);
299 byte1 = (byte2 & 0x3) << 6;
300
301 p = strchr(base64, *src++);
302 if (p == NULL) {
303 if (*(src-1) == '=') {
304 if (byte1 != 0) /* bad padding */
305 return BADPAD;
306 return 2;
307 }
308 return BADCH3;
309 }
310 byte2 = p - base64; /* last six */
311 *dst++ = byte1 | byte2;
312
313 return 3;
314 }
315
316 /*
317 - untext - convert one ASCII character to byte
318 */
319 static int /* number of result bytes, or error code */
320 untext(src, dst, dstlen)
321 const char *src; /* known to be full length */
322 char *dst;
323 size_t dstlen; /* not large enough is a failure */
324 {
325 if (dstlen < 1)
326 return SHORT;
327
328 *dst = *src;
329 return 1;
330 }
331
332 /*
333 - badch - produce a nice complaint about an unknown character
334 *
335 * If the compiler complains that the array bigenough[] has a negative
336 * size, that means the TTODATAV_BUF constant has been set too small.
337 */
338 static const char * /* literal or errp */
339 badch(src, errcode, errp, errlen)
340 const char *src;
341 int errcode;
342 char *errp; /* might be NULL */
343 size_t errlen;
344 {
345 static const char pre[] = "unknown character (`";
346 static const char suf[] = "') in input";
347 char buf[5];
348 # define REQD (sizeof(pre) - 1 + sizeof(buf) - 1 + sizeof(suf))
349 struct sizecheck {
350 char bigenough[TTODATAV_BUF - REQD]; /* see above */
351 };
352 char ch;
353
354 if (errp == NULL || errlen < REQD)
355 return "unknown character in input";
356 strcpy(errp, pre);
357 ch = *(src + BADOFF(errcode));
358 if (isprint(ch)) {
359 buf[0] = ch;
360 buf[1] = '\0';
361 } else {
362 buf[0] = '\\';
363 buf[1] = ((ch & 0700) >> 6) + '0';
364 buf[2] = ((ch & 0070) >> 3) + '0';
365 buf[3] = ((ch & 0007) >> 0) + '0';
366 buf[4] = '\0';
367 }
368 strcat(errp, buf);
369 strcat(errp, suf);
370 return (const char *)errp;
371 }
372
373
374
375 #ifdef TTODATA_MAIN
376
377 #include <stdio.h>
378
379 struct artab;
380 static void check(struct artab *r, char *buf, size_t n, err_t oops, int *status);
381 static void regress(char *pgm);
382 static void hexout(const char *s, size_t len, FILE *f);
383
384 /*
385 - main - convert first argument to hex, or run regression
386 */
387 int
388 main(int argc, char *argv[])
389 {
390 char buf[1024];
391 char buf2[1024];
392 char err[512];
393 size_t n;
394 size_t i;
395 char *p = buf;
396 char *p2 = buf2;
397 char *pgm = argv[0];
398 const char *oops;
399
400 if (argc < 2) {
401 fprintf(stderr, "Usage: %s {0x<hex>|0s<base64>|-r}\n", pgm);
402 exit(2);
403 }
404
405 if (strcmp(argv[1], "-r") == 0) {
406 regress(pgm); /* should not return */
407 fprintf(stderr, "%s: regress() returned?!?\n", pgm);
408 exit(1);
409 }
410
411 oops = ttodatav(argv[1], 0, 0, buf, sizeof(buf), &n,
412 err, sizeof(err), TTODATAV_IGNORESPACE);
413 if (oops != NULL) {
414 fprintf(stderr, "%s: ttodata error `%s' in `%s'\n", pgm,
415 oops, argv[1]);
416 exit(1);
417 }
418
419 if (n > sizeof(buf)) {
420 p = (char *)malloc((size_t)n);
421 if (p == NULL) {
422 fprintf(stderr,
423 "%s: unable to malloc %d bytes for result\n",
424 pgm, n);
425 exit(1);
426 }
427 oops = ttodata(argv[1], 0, 0, p, n, &n);
428 if (oops != NULL) {
429 fprintf(stderr, "%s: error `%s' in ttodata retry?!?\n",
430 pgm, oops);
431 exit(1);
432 }
433 }
434
435 hexout(p, n, stdout);
436 printf("\n");
437
438 i = datatot(buf, n, 'h', buf2, sizeof(buf2));
439 if (i == 0) {
440 fprintf(stderr, "%s: datatot reports error in `%s'\n", pgm,
441 argv[1]);
442 exit(1);
443 }
444
445 if (i > sizeof(buf2)) {
446 p2 = (char *)malloc((size_t)i);
447 if (p == NULL) {
448 fprintf(stderr,
449 "%s: unable to malloc %d bytes for result\n",
450 pgm, i);
451 exit(1);
452 }
453 i = datatot(buf, n, 'h', p2, i);
454 if (i == 0) {
455 fprintf(stderr, "%s: error in datatoa retry?!?\n", pgm);
456 exit(1);
457 }
458 }
459
460 printf("%s\n", p2);
461
462 exit(0);
463 }
464
465 /*
466 - hexout - output an arbitrary-length string in hex
467 */
468 static void
469 hexout(s, len, f)
470 const char *s;
471 size_t len;
472 FILE *f;
473 {
474 size_t i;
475
476 fprintf(f, "0x");
477 for (i = 0; i < len; i++)
478 fprintf(f, "%02x", (unsigned char)s[i]);
479 }
480
481 struct artab {
482 int base;
483 # define IGNORESPACE_BIAS 1000
484 char *ascii; /* NULL for end */
485 char *data; /* NULL for error expected */
486 } atodatatab[] = {
487 { 0, "", NULL, },
488 { 0, "0", NULL, },
489 { 0, "0x", NULL, },
490 { 0, "0xa", NULL, },
491 { 0, "0xab", "\xab", },
492 { 0, "0xabc", NULL, },
493 { 0, "0xabcd", "\xab\xcd", },
494 { 0, "0x0123456789", "\x01\x23\x45\x67\x89", },
495 { 0, "0x01x", NULL, },
496 { 0, "0xabcdef", "\xab\xcd\xef", },
497 { 0, "0xABCDEF", "\xab\xcd\xef", },
498 { 0, "0XaBc0eEd81f", "\xab\xc0\xee\xd8\x1f", },
499 { 0, "0XaBc0_eEd8", "\xab\xc0\xee\xd8", },
500 { 0, "0XaBc0_", NULL, },
501 { 0, "0X_aBc0", NULL, },
502 { 0, "0Xa_Bc0", NULL, },
503 { 16, "aBc0eEd8", "\xab\xc0\xee\xd8", },
504 { 0, "0s", NULL, },
505 { 0, "0sA", NULL, },
506 { 0, "0sBA", NULL, },
507 { 0, "0sCBA", NULL, },
508 { 0, "0sDCBA", "\x0c\x20\x40", },
509 { 0, "0SDCBA", "\x0c\x20\x40", },
510 { 0, "0sDA==", "\x0c", },
511 { 0, "0sDC==", NULL, },
512 { 0, "0sDCA=", "\x0c\x20", },
513 { 0, "0sDCB=", NULL, },
514 { 0, "0sDCAZ", "\x0c\x20\x19", },
515 { 0, "0sDCAa", "\x0c\x20\x1a", },
516 { 0, "0sDCAz", "\x0c\x20\x33", },
517 { 0, "0sDCA0", "\x0c\x20\x34", },
518 { 0, "0sDCA9", "\x0c\x20\x3d", },
519 { 0, "0sDCA+", "\x0c\x20\x3e", },
520 { 0, "0sDCA/", "\x0c\x20\x3f", },
521 { 0, "0sAbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
522 { IGNORESPACE_BIAS + 0, "0s AbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
523 { IGNORESPACE_BIAS + 0, "0sA braCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
524 { IGNORESPACE_BIAS + 0, "0sAb raCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
525 { IGNORESPACE_BIAS + 0, "0sAbr aCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
526 { IGNORESPACE_BIAS + 0, "0sAbra Cadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
527 { IGNORESPACE_BIAS + 0, "0sAbraC adabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
528 { IGNORESPACE_BIAS + 0, "0sAbraCa dabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
529 { IGNORESPACE_BIAS + 0, "0sAbraCad abra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
530 { IGNORESPACE_BIAS + 0, "0sAbraCada bra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
531 { IGNORESPACE_BIAS + 0, "0sAbraCadab ra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
532 { IGNORESPACE_BIAS + 0, "0sAbraCadabr a+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
533 { IGNORESPACE_BIAS + 0, "0sAbraCadabra +", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
534 { IGNORESPACE_BIAS + 0, "0sAbraCadabra+ ", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
535 { 0, "0t", NULL, },
536 { 0, "0tabc_xyz", "abc_xyz", },
537 { 256, "abc_xyz", "abc_xyz", },
538 { 0, NULL, NULL, },
539 };
540
541 struct drtab {
542 char *data; /* input; NULL for end */
543 char format;
544 int buflen; /* -1 means big buffer */
545 int outlen; /* -1 means strlen(ascii)+1 */
546 char *ascii; /* NULL for error expected */
547 } datatoatab[] = {
548 { "", 'x', -1, -1, NULL, },
549 { "", 'X', -1, -1, NULL, },
550 { "", 'n', -1, -1, NULL, },
551 { "0", 'x', -1, -1, "0x30", },
552 { "0", 'x', 0, 5, "---", },
553 { "0", 'x', 1, 5, "", },
554 { "0", 'x', 2, 5, "0", },
555 { "0", 'x', 3, 5, "0x", },
556 { "0", 'x', 4, 5, "0x3", },
557 { "0", 'x', 5, 5, "0x30", },
558 { "0", 'x', 6, 5, "0x30", },
559 { "\xab\xcd", 'x', -1, -1, "0xabcd", },
560 { "\x01\x23\x45\x67\x89", 'x', -1, -1, "0x0123456789", },
561 { "\xab\xcd\xef", 'x', -1, -1, "0xabcdef", },
562 { "\xab\xc0\xee\xd8\x1f", 'x', -1, -1, "0xabc0eed81f", },
563 { "\x01\x02", 'h', -1, -1, "0x0102", },
564 { "\x01\x02\x03\x04\x05\x06", 'h', -1, -1, "0x01020304_0506", },
565 { "\xab\xc0\xee\xd8\x1f", 16, -1, -1, "abc0eed81f", },
566 { "\x0c\x20\x40", 's', -1, -1, "0sDCBA", },
567 { "\x0c\x20\x40", 's', 0, 7, "---", },
568 { "\x0c\x20\x40", 's', 1, 7, "", },
569 { "\x0c\x20\x40", 's', 2, 7, "0", },
570 { "\x0c\x20\x40", 's', 3, 7, "0s", },
571 { "\x0c\x20\x40", 's', 4, 7, "0sD", },
572 { "\x0c\x20\x40", 's', 5, 7, "0sDC", },
573 { "\x0c\x20\x40", 's', 6, 7, "0sDCB", },
574 { "\x0c\x20\x40", 's', 7, 7, "0sDCBA", },
575 { "\x0c\x20\x40", 's', 8, 7, "0sDCBA", },
576 { "\x0c", 's', -1, -1, "0sDA==", },
577 { "\x0c\x20", 's', -1, -1, "0sDCA=", },
578 { "\x0c\x20\x19", 's', -1, -1, "0sDCAZ", },
579 { "\x0c\x20\x1a", 's', -1, -1, "0sDCAa", },
580 { "\x0c\x20\x33", 's', -1, -1, "0sDCAz", },
581 { "\x0c\x20\x34", 's', -1, -1, "0sDCA0", },
582 { "\x0c\x20\x3d", 's', -1, -1, "0sDCA9", },
583 { "\x0c\x20\x3e", 's', -1, -1, "0sDCA+", },
584 { "\x0c\x20\x3f", 's', -1, -1, "0sDCA/", },
585 { "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 's', -1, -1, "0sAbraCadabra+", },
586 { "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 64, -1, -1, "AbraCadabra+", },
587 { NULL, 'x', -1, -1, NULL, },
588 };
589
590 /*
591 - regress - regression-test ttodata() and datatot()
592 */
593 static void
594 check(r, buf, n, oops, status)
595 struct artab *r;
596 char *buf;
597 size_t n;
598 err_t oops;
599 int *status;
600 {
601 if (oops != NULL && r->data == NULL)
602 {} /* error expected */
603 else if (oops != NULL) {
604 printf("`%s' gave error `%s', expecting %d `", r->ascii,
605 oops, strlen(r->data));
606 hexout(r->data, strlen(r->data), stdout);
607 printf("'\n");
608 *status = 1;
609 } else if (r->data == NULL) {
610 printf("`%s' gave %d `", r->ascii, n);
611 hexout(buf, n, stdout);
612 printf("', expecting error\n");
613 *status = 1;
614 } else if (n != strlen(r->data)) {
615 printf("length wrong in `%s': got %d `", r->ascii, n);
616 hexout(buf, n, stdout);
617 printf("', expecting %d `", strlen(r->data));
618 hexout(r->data, strlen(r->data), stdout);
619 printf("'\n");
620 *status = 1;
621 } else if (memcmp(buf, r->data, n) != 0) {
622 printf("`%s' gave %d `", r->ascii, n);
623 hexout(buf, n, stdout);
624 printf("', expecting %d `", strlen(r->data));
625 hexout(r->data, strlen(r->data), stdout);
626 printf("'\n");
627 *status = 1;
628 }
629 fflush(stdout);
630 }
631
632 static void /* should not return at all, in fact */
633 regress(pgm)
634 char *pgm;
635 {
636 struct artab *r;
637 struct drtab *dr;
638 char buf[100];
639 size_t n;
640 int status = 0;
641
642 for (r = atodatatab; r->ascii != NULL; r++) {
643 int base = r->base;
644 int xbase = 0;
645
646 if ((base == 0 || base == IGNORESPACE_BIAS + 0) && r->ascii[0] == '0') {
647 switch (r->ascii[1]) {
648 case 'x':
649 case 'X':
650 xbase = 16;
651 break;
652 case 's':
653 case 'S':
654 xbase = 64;
655 break;
656 case 't':
657 case 'T':
658 xbase = 256;
659 break;
660 }
661 }
662
663 if (base >= IGNORESPACE_BIAS) {
664 base = base - IGNORESPACE_BIAS;
665 check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
666 if (xbase != 0)
667 check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
668 } else {
669 check(r, buf, n, ttodata(r->ascii, 0, base, buf, sizeof(buf), &n), &status);
670 if (base == 64 || xbase == 64)
671 check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
672 if (xbase != 0) {
673 check(r, buf, n, ttodata(r->ascii+2, 0, xbase, buf, sizeof(buf), &n), &status);
674 if (base == 64 || xbase == 64)
675 check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
676 }
677 }
678 }
679 for (dr = datatoatab; dr->data != NULL; dr++) {
680 size_t should;
681
682 strcpy(buf, "---");
683 n = datatot(dr->data, strlen(dr->data), dr->format, buf,
684 (dr->buflen == -1) ? sizeof(buf) : dr->buflen);
685 should = (dr->ascii == NULL) ? 0 : strlen(dr->ascii) + 1;
686 if (dr->outlen != -1)
687 should = dr->outlen;
688 if (n == 0 && dr->ascii == NULL)
689 {} /* error expected */
690 else if (n == 0) {
691 printf("`");
692 hexout(dr->data, strlen(dr->data), stdout);
693 printf("' %c gave error, expecting %d `%s'\n",
694 dr->format, should, dr->ascii);
695 status = 1;
696 } else if (dr->ascii == NULL) {
697 printf("`");
698 hexout(dr->data, strlen(dr->data), stdout);
699 printf("' %c gave %d `%.*s', expecting error\n",
700 dr->format, n, (int)n, buf);
701 status = 1;
702 } else if (n != should) {
703 printf("length wrong in `");
704 hexout(dr->data, strlen(dr->data), stdout);
705 printf("': got %d `%s'", n, buf);
706 printf(", expecting %d `%s'\n", should, dr->ascii);
707 status = 1;
708 } else if (strcmp(buf, dr->ascii) != 0) {
709 printf("`");
710 hexout(dr->data, strlen(dr->data), stdout);
711 printf("' gave %d `%s'", n, buf);
712 printf(", expecting %d `%s'\n", should, dr->ascii);
713 status = 1;
714 }
715 fflush(stdout);
716 }
717 exit(status);
718 }
719
720 #endif /* TTODATA_MAIN */