00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <fcntl.h>
00022 #include <limits.h>
00023 #include <stddef.h>
00024 #include <stdio.h>
00025 #include <stdint.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <unistd.h>
00029 #include <ctype.h>
00030
00031 #include <ccn/charbuf.h>
00032 #include <ccn/coding.h>
00033 #include <ccn/extend_dict.h>
00034
00035 static void
00036 usage(const char *progname)
00037 {
00038 fprintf(stderr,
00039 "usage: %s [-h] [-b] [-t] [-v] [-x] [-s prefix] [-d dict]* file ...\n"
00040 " Utility to convert ccn binary encoded data into XML form.\n"
00041 " -b force (base64 or hex) Binary output instead of text\n"
00042 " -t test, when specified, should be only switch\n"
00043 " -v verbose - do extra decoding as comments\n"
00044 " -x prefer hex output to base64\n"
00045 " -s pat provide a single pattern to be used when "
00046 "splitting one or more input files\n"
00047 " -d dict use this option one or more times to specify additional\n"
00048 " csv format dictionary files that extend the builtin dtag table\n"
00049 " switches may not be mixed with file name arguments\n"
00050 " use - for file to specify stdin\n"
00051 " in absence of -s option, result is on stdout\n",
00052 progname);
00053 exit(1);
00054 }
00055
00056 #define CCN_NO_SCHEMA INT_MIN
00057 #define CCN_UNKNOWN_SCHEMA (INT_MIN+1)
00058
00059 struct ccn_decoder_stack_item {
00060 size_t nameindex;
00061 size_t savedss;
00062 int saved_schema;
00063 int saved_schema_state;
00064 struct ccn_decoder_stack_item *link;
00065 };
00066
00067 struct ccn_decoder;
00068 enum callback_kind {
00069 CALLBACK_INITIAL,
00070 CALLBACK_OBJECTEND,
00071 CALLBACK_FINAL
00072 };
00073
00074 typedef void (*ccn_decoder_callback)(
00075 struct ccn_decoder *d,
00076 enum callback_kind kind,
00077 void *data
00078 );
00079
00080 struct ccn_decoder {
00081 int state;
00082 int tagstate;
00083 int bits;
00084 size_t numval;
00085 uintmax_t bignumval;
00086 int schema;
00087 int sstate;
00088 struct ccn_decoder_stack_item *stack;
00089 struct ccn_charbuf *stringstack;
00090 const struct ccn_dict_entry *tagdict;
00091 int tagdict_count;
00092 ccn_decoder_callback callback;
00093 void *callbackdata;
00094 int formatting_flags;
00095 int base64_char_count;
00096 struct ccn_charbuf *annotation;
00097 };
00098
00099 #define FORCE_BINARY (1 << 0)
00100 #define PREFER_HEX (1 << 1)
00101 #define VERBOSE_DECODE (1 << 2)
00102
00103 struct ccn_decoder *
00104 ccn_decoder_create(int formatting_flags, const struct ccn_dict *dtags)
00105 {
00106 struct ccn_decoder *d;
00107 d = calloc(1, sizeof(*d));
00108 d->stringstack = ccn_charbuf_create();
00109 if (d->stringstack == NULL) {
00110 free(d);
00111 d = NULL;
00112 return(NULL);
00113 }
00114 d->schema = CCN_NO_SCHEMA;
00115 d->tagdict = dtags->dict;
00116 d->tagdict_count = dtags->count;
00117 d->formatting_flags = formatting_flags;
00118 d->annotation = NULL;
00119 return(d);
00120 }
00121
00122 void
00123 ccn_decoder_set_callback(struct ccn_decoder *d, ccn_decoder_callback c, void *data)
00124 {
00125 d->callback = c;
00126 if (c == NULL) {
00127 d->callbackdata = NULL;
00128 } else {
00129 d->callbackdata = data;
00130 c(d, CALLBACK_INITIAL, data);
00131 }
00132 }
00133
00134 struct ccn_decoder_stack_item *
00135 ccn_decoder_push(struct ccn_decoder *d)
00136 {
00137 struct ccn_decoder_stack_item *s;
00138 s = calloc(1, sizeof(*s));
00139 if (s != NULL) {
00140 s->link = d->stack;
00141 s->savedss = d->stringstack->length;
00142 s->saved_schema = d->schema;
00143 s->saved_schema_state = d->sstate;
00144 d->stack = s;
00145 }
00146 return(s);
00147 }
00148
00149 void
00150 ccn_decoder_pop(struct ccn_decoder *d)
00151 {
00152 struct ccn_decoder_stack_item *s = d->stack;
00153 if (s != NULL) {
00154 d->stack = s->link;
00155 d->stringstack->length = s->savedss;
00156 d->schema = s->saved_schema;
00157 d->sstate = s->saved_schema_state;
00158 free(s);
00159 }
00160 }
00161
00162 void
00163 ccn_decoder_destroy(struct ccn_decoder **dp)
00164 {
00165 struct ccn_decoder *d = *dp;
00166 if (d != NULL) {
00167 if (d->callback != NULL) {
00168 d->callback(d, CALLBACK_FINAL, d->callbackdata);
00169 }
00170 while (d->stack != NULL) {
00171 ccn_decoder_pop(d);
00172 }
00173 ccn_charbuf_destroy(&(d->stringstack));
00174 free(d);
00175 *dp = NULL;
00176 }
00177 }
00178
00179 static const char *
00180 dict_name_from_number(int ndx, const struct ccn_dict_entry *dict, int n)
00181 {
00182 int i;
00183 for (i = 0; i < n; i++)
00184 if (ndx == dict[i].index)
00185 return (dict[i].name);
00186 return (NULL);
00187 }
00188
00189 static const char Base64[] =
00190 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00191
00192 static int
00193 is_text_encodable(unsigned char p[], size_t start, size_t length)
00194 {
00195 size_t i;
00196
00197 if (length == 0) return (0);
00198 for (i = 0; i < length; i++) {
00199 char c = p[start + i];
00200 if (c < ' ' || c > '~') return (0);
00201 if (c == '<' || c == '>' || c == '&') return (0);
00202 }
00203 return (1);
00204 }
00205
00206
00207 static void
00208 print_percent_escaped(const unsigned char *data, size_t size)
00209 {
00210 size_t i;
00211 unsigned char ch;
00212 for (i = 0; i < size && data[i] == '.'; i++)
00213 continue;
00214
00215 if (i == size)
00216 printf("...");
00217 for (i = 0; i < size; i++) {
00218 ch = data[i];
00219
00220
00221
00222
00223 if (('a' <= ch && ch <= 'z') ||
00224 ('A' <= ch && ch <= 'Z') ||
00225 ('0' <= ch && ch <= '9') ||
00226 ch == '-' || ch == '.' || ch == '_' || ch == '~')
00227 printf("%c", ch);
00228 else
00229 printf("%%%02X", (unsigned)ch);
00230 }
00231 }
00232
00233 size_t
00234 ccn_decoder_decode(struct ccn_decoder *d, unsigned char p[], size_t n)
00235 {
00236 int state = d->state;
00237 int tagstate = 0;
00238 size_t numval = d->numval;
00239 size_t i = 0;
00240 unsigned char c;
00241 size_t chunk;
00242 struct ccn_decoder_stack_item *s;
00243 const char *tagname;
00244 while (i < n) {
00245 switch (state) {
00246 case 0:
00247 if (tagstate > 1 && tagstate-- == 2) {
00248 printf("\"");
00249 ccn_decoder_pop(d);
00250 }
00251 if (p[i] == CCN_CLOSE) {
00252 i++;
00253 s = d->stack;
00254 if (s == NULL || tagstate > 1) {
00255 state = -__LINE__;
00256 break;
00257 }
00258 if (tagstate == 1) {
00259 tagstate = 0;
00260 printf("/>");
00261 }
00262 else if (d->schema == -1-CCN_PROCESSING_INSTRUCTIONS) {
00263 printf("?>");
00264 if (d->sstate != 2) {
00265 state = -__LINE__;
00266 break;
00267 }
00268 }
00269 else {
00270 printf("</%s>", d->stringstack->buf + s->nameindex);
00271 }
00272 if (d->annotation != NULL) {
00273 if (d->annotation->length > 0) {
00274 printf("<!-- ");
00275 print_percent_escaped(d->annotation->buf, d->annotation->length);
00276 printf(" -->");
00277 }
00278 ccn_charbuf_destroy(&d->annotation);
00279 }
00280 ccn_decoder_pop(d);
00281 if (d->stack == NULL) {
00282 if (d->callback != NULL)
00283 d->callback(d, CALLBACK_OBJECTEND, d->callbackdata);
00284 else
00285 printf("\n");
00286 }
00287 break;
00288 }
00289 numval = 0;
00290 state = 1;
00291
00292 case 1:
00293 c = p[i++];
00294 if ((c & CCN_TT_HBIT) == CCN_CLOSE) {
00295 if (numval > (numval << 7)) {
00296 state = 9;
00297 d->bignumval = numval;
00298 i--;
00299 continue;
00300 }
00301 numval = (numval << 7) + (c & 127);
00302 if (numval > (numval << (7-CCN_TT_BITS))) {
00303 state = 9;
00304 d->bignumval = numval;
00305 }
00306 }
00307 else {
00308 numval = (numval << (7-CCN_TT_BITS)) +
00309 ((c >> CCN_TT_BITS) & CCN_MAX_TINY);
00310 c &= CCN_TT_MASK;
00311 switch (c) {
00312 case CCN_EXT:
00313 if (tagstate == 1) {
00314 tagstate = 0;
00315 printf(">");
00316 }
00317 s = ccn_decoder_push(d);
00318 s->nameindex = d->stringstack->length;
00319 d->schema = -1-numval;
00320 d->sstate = 0;
00321 switch (numval) {
00322 case CCN_PROCESSING_INSTRUCTIONS:
00323 printf("<?");
00324 break;
00325 default:
00326 state = -__LINE__;
00327 }
00328 state = 0;
00329 break;
00330 case CCN_DTAG:
00331 if (tagstate == 1) {
00332 tagstate = 0;
00333 printf(">");
00334 }
00335 s = ccn_decoder_push(d);
00336 s->nameindex = d->stringstack->length;
00337 d->schema = numval;
00338 d->sstate = 0;
00339 tagname = NULL;
00340 if (numval <= INT_MAX)
00341 tagname = dict_name_from_number(numval, d->tagdict, d->tagdict_count);
00342 if (tagname == NULL) {
00343 fprintf(stderr,
00344 "*** Warning: unrecognized DTAG %lu\n",
00345 (unsigned long)numval);
00346 ccn_charbuf_append(d->stringstack,
00347 "UNKNOWN_DTAG",
00348 sizeof("UNKNOWN_DTAG"));
00349 printf("<%s code=\"%lu\"",
00350 d->stringstack->buf + s->nameindex,
00351 (unsigned long)d->schema);
00352 d->schema = CCN_UNKNOWN_SCHEMA;
00353 }
00354 else {
00355 ccn_charbuf_append(d->stringstack, tagname, strlen(tagname)+1);
00356 printf("<%s", tagname);
00357 }
00358 if ((d->formatting_flags & VERBOSE_DECODE) != 0) {
00359 if (d->annotation != NULL)
00360 abort();
00361 if (numval == 15 )
00362 d->annotation = ccn_charbuf_create();
00363 }
00364 tagstate = 1;
00365 state = 0;
00366 break;
00367 case CCN_BLOB:
00368 if (numval > n - i) {
00369 state = -__LINE__;
00370 break;
00371 }
00372 if (tagstate == 1) {
00373 tagstate = 0;
00374 if ((d->formatting_flags & FORCE_BINARY) == 0 && is_text_encodable(p, i, numval)) {
00375 printf(" ccnbencoding=\"text\">");
00376 state = 6;
00377 }
00378 else if ((d->formatting_flags & PREFER_HEX) != 0) {
00379 printf(" ccnbencoding=\"hexBinary\">");
00380 state = 2;
00381 }
00382 else {
00383 printf(" ccnbencoding=\"base64Binary\">");
00384 state = 10;
00385 }
00386 }
00387 else {
00388 fprintf(stderr, "blob not tagged in xml output\n");
00389 state = 10;
00390 }
00391 state = (numval == 0) ? 0 : state;
00392 d->base64_char_count = 0;
00393 break;
00394 case CCN_UDATA:
00395 if (tagstate == 1) {
00396 tagstate = 0;
00397 printf(">");
00398 }
00399 state = 3;
00400 if (d->schema == -1-CCN_PROCESSING_INSTRUCTIONS) {
00401 if (d->sstate > 0) {
00402 printf(" ");
00403 }
00404 state = 6;
00405 d->sstate += 1;
00406 }
00407 if (numval == 0)
00408 state = 0;
00409 break;
00410 case CCN_DATTR:
00411 if (tagstate != 1) {
00412 state = -__LINE__;
00413 break;
00414 }
00415 s = ccn_decoder_push(d);
00416 ccn_charbuf_reserve(d->stringstack, 1);
00417 s->nameindex = d->stringstack->length;
00418 printf(" UNKNOWN_DATTR_%lu=\"", (unsigned long)numval);
00419 tagstate = 3;
00420 state = 0;
00421 break;
00422 case CCN_ATTR:
00423 if (tagstate != 1) {
00424 state = -__LINE__;
00425 break;
00426 }
00427 if (numval >= n - i) {
00428 state = -__LINE__;
00429 break;
00430 }
00431 numval += 1;
00432 s = ccn_decoder_push(d);
00433 ccn_charbuf_reserve(d->stringstack, numval + 1);
00434 s->nameindex = d->stringstack->length;
00435 state = 5;
00436 break;
00437 case CCN_TAG:
00438 if (tagstate == 1) {
00439 tagstate = 0;
00440 printf(">");
00441 }
00442 if (numval >= n - i) {
00443 state = -__LINE__;
00444 break;
00445 }
00446 numval += 1;
00447 s = ccn_decoder_push(d);
00448 ccn_charbuf_reserve(d->stringstack, numval + 1);
00449 s->nameindex = d->stringstack->length;
00450 state = 4;
00451 break;
00452 default:
00453 state = -__LINE__;
00454 }
00455 }
00456 break;
00457 case 2:
00458 c = p[i++];
00459 if (d->annotation != NULL)
00460 ccn_charbuf_append_value(d->annotation, c, 1);
00461 printf("%02X", c);
00462 if (--numval == 0) {
00463 state = 0;
00464 }
00465 break;
00466 case 3:
00467 c = p[i++];
00468 if (--numval == 0) {
00469 state = 0;
00470 }
00471 switch (c) {
00472 case 0:
00473 state = -__LINE__;
00474 break;
00475 case '&':
00476 printf("&");
00477 break;
00478 case '<':
00479 printf("<");
00480 break;
00481 case '>':
00482 printf(">");
00483 break;
00484 case '"':
00485 printf(""");
00486 break;
00487 default:
00488 printf("%c", c);
00489 }
00490 break;
00491 case 4:
00492 case 5:
00493 chunk = n - i;
00494 if (chunk > numval) {
00495 chunk = numval;
00496 }
00497 if (chunk == 0) {
00498 state = -__LINE__;
00499 break;
00500 }
00501 ccn_charbuf_append(d->stringstack, p + i, chunk);
00502 numval -= chunk;
00503 i += chunk;
00504 if (numval == 0) {
00505 ccn_charbuf_append(d->stringstack, (const unsigned char *)"\0", 1);
00506 s = d->stack;
00507 if (s == NULL ||
00508 strlen((char*)d->stringstack->buf + s->nameindex) !=
00509 d->stringstack->length -1 - s->nameindex) {
00510 state = -__LINE__;
00511 break;
00512 }
00513 if (state == 4) {
00514 printf("<%s", d->stringstack->buf + s->nameindex);
00515 tagstate = 1;
00516 }
00517 else {
00518 printf(" %s=\"", d->stringstack->buf + s->nameindex);
00519 tagstate = 3;
00520 }
00521 state = 0;
00522 }
00523 break;
00524 case 6:
00525 c = p[i++];
00526 if (--numval == 0) {
00527 state = 0;
00528 }
00529 printf("%c", c);
00530 break;
00531 case 9:
00532 c = p[i++];
00533 if ((c & CCN_TT_HBIT) == CCN_CLOSE) {
00534 d->bignumval = (d->bignumval << 7) + (c & 127);
00535 }
00536 else {
00537 d->bignumval = (d->bignumval << (7-CCN_TT_BITS)) +
00538 ((c >> CCN_TT_BITS) & CCN_MAX_TINY);
00539 c &= CCN_TT_MASK;
00540 if (tagstate == 1) {
00541 tagstate = 0;
00542 printf(">");
00543 }
00544
00545
00546
00547
00548
00549 switch (c) {
00550 default:
00551 state = -__LINE__;
00552 }
00553 }
00554 break;
00555 case 10:
00556 c = p[i++];
00557 if (d->annotation != NULL)
00558 ccn_charbuf_append_value(d->annotation, c, 1);
00559 printf("%c", Base64[c >> 2]);
00560 d->base64_char_count++;
00561 if (--numval == 0) {
00562 printf("%c==", Base64[(c & 3) << 4]);
00563 state = 0;
00564 d->base64_char_count += 3;
00565 }
00566 else {
00567 d->bits = (c & 3);
00568 state = 11;
00569 }
00570 if ((d->formatting_flags & FORCE_BINARY) == 0 && d->base64_char_count >= 64) {
00571 d->base64_char_count = 0;
00572 printf("\n");
00573 }
00574 break;
00575 case 11:
00576 c = p[i++];
00577 if (d->annotation != NULL)
00578 ccn_charbuf_append_value(d->annotation, c, 1);
00579 printf("%c", Base64[((d->bits & 3) << 4) + (c >> 4)]);
00580 d->base64_char_count++;
00581 if (--numval == 0) {
00582 printf("%c=", Base64[(c & 0xF) << 2]);
00583 state = 0;
00584 d->base64_char_count += 2;
00585 }
00586 else {
00587 d->bits = (c & 0xF);
00588 state = 12;
00589 }
00590 if ((d->formatting_flags & FORCE_BINARY) == 0 && d->base64_char_count >= 64) {
00591 d->base64_char_count = 0;
00592 printf("\n");
00593 }
00594 break;
00595 case 12:
00596 c = p[i++];
00597 if (d->annotation != NULL)
00598 ccn_charbuf_append_value(d->annotation, c, 1);
00599 printf("%c%c", Base64[((d->bits & 0xF) << 2) + (c >> 6)],
00600 Base64[c & 0x3F]);
00601 d->base64_char_count += 2;
00602 if (--numval == 0) {
00603 state = 0;
00604 }
00605 else {
00606 state = 10;
00607 }
00608 if ((d->formatting_flags & FORCE_BINARY) == 0 && d->base64_char_count >= 64) {
00609 d->base64_char_count = 0;
00610 printf("\n");
00611 }
00612 break;
00613 default:
00614 n = i;
00615 }
00616 }
00617 d->state = state;
00618 d->tagstate = tagstate;
00619 d->numval = numval;
00620 return(i);
00621 }
00622
00623 static int
00624 process_data(struct ccn_decoder *d, unsigned char *data, size_t n)
00625 {
00626 int res = 0;
00627 size_t s;
00628 printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
00629 s = ccn_decoder_decode(d, data, n);
00630 if (d->state != 0 || s < n || d->stack != NULL || d->tagstate != 0) {
00631 res = 1;
00632 fprintf(stderr, "error state %d after %d of %d chars\n",
00633 (int)d->state, (int)s, (int)n);
00634 }
00635 return(res);
00636 }
00637
00638 static int
00639 process_fd(struct ccn_decoder *d, int fd)
00640 {
00641 struct ccn_charbuf *c = ccn_charbuf_create();
00642 ssize_t len;
00643 int res = 0;
00644 for (;;) {
00645 unsigned char *p = ccn_charbuf_reserve(c, 80);
00646 if (p == NULL) {
00647 perror("ccn_charbuf_reserve");
00648 res = 1;
00649 break;
00650 }
00651 len = read(fd, p, c->limit - c->length);
00652 if (len <= 0) {
00653 if (len == -1) {
00654 perror("read");
00655 res = 1;
00656 }
00657 break;
00658 }
00659 c->length += len;
00660 }
00661 fprintf(stderr, " <!-- input is %6lu bytes -->\n", (unsigned long)c->length);
00662 res |= process_data(d, c->buf, c->length);
00663 ccn_charbuf_destroy(&c);
00664 return(res);
00665 }
00666
00667
00668 static int
00669 process_file(char *path, int formatting_flags, const struct ccn_dict *dtags)
00670 {
00671 int fd = 0;
00672 int res = 0;
00673 struct ccn_decoder *d;
00674
00675 if (0 != strcmp(path, "-")) {
00676 fd = open(path, O_RDONLY);
00677 if (-1 == fd) {
00678 perror(path);
00679 return(1);
00680 }
00681 }
00682
00683 d = ccn_decoder_create(formatting_flags, dtags);
00684 if (d == NULL) {
00685 fprintf(stderr, "Unable to allocate decoder\n");
00686 return(1);
00687 }
00688 res = process_fd(d, fd);
00689 ccn_decoder_destroy(&d);
00690
00691 if (fd > 0)
00692 close(fd);
00693 return(res);
00694 }
00695
00696 struct callback_state {
00697 int fragment;
00698 char *fileprefix;
00699 };
00700
00701 static void
00702 set_stdout(struct ccn_decoder *d, enum callback_kind kind, void *data)
00703 {
00704 struct callback_state *cs = (struct callback_state *)data;
00705 char filename[256];
00706 FILE *fp;
00707 switch (kind) {
00708 case CALLBACK_INITIAL:
00709 case CALLBACK_OBJECTEND:
00710 snprintf(filename, sizeof(filename), "%s%05d.xml", cs->fileprefix, cs->fragment++);
00711 fprintf(stderr, " <!-- attaching stdout to %s --!>\n", filename);
00712 fp = freopen(filename, "w+", stdout);
00713 if (fp == NULL)
00714 perror(filename);
00715 break;
00716 case CALLBACK_FINAL:
00717 fflush(stdout);
00718 fclose(stdout);
00719 free(cs);
00720 break;
00721 }
00722 }
00723
00724 static int
00725 process_split_file(char *base, char *path, int formatting_flags,
00726 const struct ccn_dict *dtags, int *suffix)
00727 {
00728 int fd = 0;
00729 int res = 0;
00730 struct ccn_decoder *d;
00731 struct callback_state *cs;
00732
00733 if (0 != strcmp(path, "-")) {
00734 fd = open(path, O_RDONLY);
00735 if (-1 == fd) {
00736 perror(path);
00737 return(1);
00738 }
00739 }
00740
00741 cs = calloc(1, sizeof(*cs));
00742 cs->fileprefix = base;
00743 cs->fragment = *suffix;
00744 d = ccn_decoder_create(formatting_flags, dtags);
00745 if (d == NULL) {
00746 fprintf(stderr, "Unable to allocate decoder\n");
00747 return(1);
00748 }
00749 ccn_decoder_set_callback(d, set_stdout, cs);
00750 res = process_fd(d, fd);
00751 *suffix = cs->fragment;
00752 ccn_decoder_destroy(&d);
00753 if (fd > 0)
00754 close(fd);
00755 return(res);
00756 }
00757
00758 #define L (CCN_TT_HBIT & ~CCN_CLOSE)
00759 unsigned char test1[] = {
00760 (2 << CCN_TT_BITS) + CCN_TAG + L, 'F', 'o', 'o',
00761 (0 << CCN_TT_BITS) + CCN_TAG + L, 'a',
00762 (1 << CCN_TT_BITS) + CCN_UDATA + L, 'X',
00763 CCN_CLOSE,
00764 (0 << CCN_TT_BITS) + CCN_TAG + L, 'b',
00765 (3 << CCN_TT_BITS) + CCN_ATTR + L, 't', 'y', 'p', 'e',
00766 (5 << CCN_TT_BITS) + CCN_UDATA + L, 'e', 'm', 'p', 't', 'y',
00767 CCN_CLOSE,
00768 (2 << CCN_TT_BITS) + CCN_TAG + L, 'b', 'i', 'n',
00769 (4 << CCN_TT_BITS) + CCN_BLOB + L, 1, 0x23, 0x45, 0x67,
00770 CCN_CLOSE,
00771 (CCN_CLOSE + ((20-1) >> (7-CCN_TT_BITS))),
00772 (((20-1) & CCN_TT_MASK) << CCN_TT_BITS) + CCN_TAG + L,
00773 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'd',
00774 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'd',
00775 'a', 'b', 'c', 'd',
00776 CCN_CLOSE,
00777 (2 << CCN_TT_BITS) + CCN_TAG + L, 'i', 'n', 't',
00778 (3 << CCN_TT_BITS) + CCN_ATTR + L, 't', 'y', 'p', 'e',
00779 (3 << CCN_TT_BITS) + CCN_UDATA + L, 'B', 'I', 'G',
00780 CCN_CLOSE,
00781 (6 << CCN_TT_BITS) + CCN_UDATA + L,
00782 'H','i','&','b','y','e',
00783 CCN_CLOSE,
00784 };
00785
00786 int
00787 main(int argc, char **argv)
00788 {
00789 extern char *optarg;
00790 extern int optind, optopt;
00791 int opt;
00792 int tflag = 0, formatting_flags = 0, errflag = 0;
00793 char *sarg = NULL;
00794 int res = 0;
00795 int suffix = 0;
00796 struct ccn_decoder *d;
00797 struct ccn_dict *dtags = (struct ccn_dict *)&ccn_dtag_dict;
00798
00799 while ((opt = getopt(argc, argv, ":hbd:s:tvx")) != -1) {
00800 switch (opt) {
00801 case 'h':
00802 usage(argv[0]);
00803 break;
00804 case 'b':
00805 formatting_flags |= FORCE_BINARY;
00806 break;
00807 case 'd':
00808 if (0 != ccn_extend_dict(optarg, dtags, &dtags)) {
00809 fprintf(stderr, "Unable to load dtag dictionary %s\n", optarg);
00810 errflag = 1;
00811 }
00812 break;
00813 case 's':
00814 sarg = optarg;
00815 break;
00816 case 't':
00817 tflag = 1;
00818 break;
00819 case 'v':
00820 formatting_flags |= VERBOSE_DECODE;
00821 break;
00822 case 'x':
00823 formatting_flags |= PREFER_HEX;
00824 break;
00825 case '?':
00826 fprintf(stderr, "Unrecognized option: -%c\n", optopt);
00827 errflag = 1;
00828 }
00829 }
00830 if (tflag && (sarg != NULL || formatting_flags != 0))
00831 errflag = 1;
00832
00833 if (errflag || (tflag && (optind < argc)))
00834 usage(argv[0]);
00835
00836 if (tflag) {
00837 d = ccn_decoder_create(1, &ccn_dtag_dict);
00838 if (d == NULL) {
00839 fprintf(stderr, "Unable to allocate decoder\n");
00840 exit(1);
00841 }
00842 res |= process_data(d, test1, sizeof(test1));
00843 ccn_decoder_destroy(&d);
00844 return (res);
00845 }
00846
00847 for (suffix = 0; optind < argc; optind++) {
00848 if (sarg) {
00849 fprintf(stderr, "<!-- Processing %s into %s -->\n", argv[optind], sarg);
00850 res |= process_split_file(sarg, argv[optind], formatting_flags,
00851 dtags, &suffix);
00852 }
00853 else {
00854 fprintf(stderr, "<!-- Processing %s -->\n", argv[optind]);
00855 res |= process_file(argv[optind], formatting_flags, dtags);
00856 }
00857 }
00858 return(res);
00859 }
00860