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