Date: Thu, 31 Jul 2014 05:07:26 -0400 From: Phil Shafer <phil@juniper.net> To: "Simon J. Gerraty" <sjg@juniper.net> Cc: Alfred Perlstein <alfred@freebsd.org>, freebsd-arch@freebsd.org Subject: Re: XML Output: libxo - provide single API to output TXT, XML, JSON and HTML Message-ID: <201407310907.s6V97Qsw092908@idle.juniper.net> In-Reply-To: <20140730235123.AC944580A2@chaos.jnpr.net>
next in thread | previous in thread | raw e-mail | index | archive | help
"Simon J. Gerraty" writes: >We now have an API and library that can avoid the need to double the >cost of adding new output to apps, ie you only write to libxo's api >and it does plain TXT for you if needed. I'm appending another example, using "wc". I've added the "xo" equivalent of warn/warnx/err/errx/etc. Normally, they'll make the expected noise on stderr, but with the XO_WARN_XML flag, they generate XML content on the stdout (or whatever xo_handle_t is in use). I don't have a JSON equivalent because, well, I don't know what the json equivalent would look like. There's also a xo_attr function that will add an attribute to the next element emitted, so one can: xo_attr("seconds", stop - start); xo_emit("{:time}", fancy_time(stop - start)); to make: <time seconds="600">10 minutes</time> There's also the "printf(1)" equivalent command "xo" for use in shell scripts: % xo --wrap response/data 'The {:animal} is {:color} and {:mood}\n' bear brown angry The bear is brown and angry % xo -X -p --wrap response/data 'The {:animal} is {:color} and {:mood}\n' bear brown angry <response> <data> <animal>bear</animal> <color>brown</color> <mood>angry</mood> </data> </response> The code is in github: https://github.com/Juniper/libxo HTML docs are here: http://juniper.github.io/libxo/libxo-manual.html Text/source docs are here: https://raw.githubusercontent.com/Juniper/libxo/master/doc/libxo.txt I'm using the common master/develop branching scheme, so "master" should be stable, while "develop" is where I'm working. Simon said there's a github mirror for freebsd, so I make fork that and add the patches for the various utilities I'm working thru. Thanks, Phil ----------- diff -rbu /usr/src/usr.bin/wc/wc.c ./wc.c --- /usr/src/usr.bin/wc/wc.c 2010-12-21 12:09:25.000000000 -0500 +++ ./wc.c 2014-07-31 04:20:15.000000000 -0400 @@ -61,6 +61,7 @@ #include <unistd.h> #include <wchar.h> #include <wctype.h> +#include <libxo/libxo.h> uintmax_t tlinect, twordct, tcharct, tlongline; int doline, doword, dochar, domulti, dolongline; @@ -105,33 +106,45 @@ if (doline + doword + dochar + domulti + dolongline == 0) doline = doword = dochar = 1; + xo_open_container("wc"); + xo_open_list("file"); errors = 0; total = 0; if (!*argv) { + xo_open_instance("file"); if (cnt((char *)NULL) != 0) ++errors; else - (void)printf("\n"); + xo_emit("\n"); + xo_close_instance("file"); } else do { + xo_open_instance("file"); + xo_emit(" {ek:filename/%s}\n", *argv); if (cnt(*argv) != 0) ++errors; else - (void)printf(" %s\n", *argv); + xo_emit(" {d:filename/%s}\n", *argv); + xo_close_instance("file"); ++total; } while(*++argv); + xo_close_list("file"); if (total > 1) { + xo_open_container("total"); if (doline) - (void)printf(" %7ju", tlinect); + xo_emit(" {:lines/%7ju/%ju}", tlinect); if (doword) - (void)printf(" %7ju", twordct); + xo_emit(" {:words/%7ju/%ju", twordct); if (dochar || domulti) - (void)printf(" %7ju", tcharct); + xo_emit(" {:characters/%7ju/%ju}", tcharct); if (dolongline) - (void)printf(" %7ju", tlongline); - (void)printf(" total\n"); + xo_emit(" {:long-lines/%7ju/%ju}", tlongline); + xo_emit(" total\n"); + xo_close_container("total"); } + xo_close_container("wc"); + xo_flush(); exit(errors == 0 ? 0 : 1); } @@ -154,7 +167,7 @@ fd = STDIN_FILENO; } else { if ((fd = open(file, O_RDONLY, 0)) < 0) { - warn("%s: open", file); + xo_warn("%s: open", file); return (1); } if (doword || (domulti && MB_CUR_MAX != 1)) @@ -167,7 +180,7 @@ if (doline) { while ((len = read(fd, buf, MAXBSIZE))) { if (len == -1) { - warn("%s: read", file); + xo_warn("%s: read", file); (void)close(fd); return (1); } @@ -182,15 +195,15 @@ tmpll++; } tlinect += linect; - (void)printf(" %7ju", linect); + xo_emit(" {:lines/%7ju/%ju}", linect); if (dochar) { tcharct += charct; - (void)printf(" %7ju", charct); + xo_emit(" {:characters/%7ju/%ju}", charct); } if (dolongline) { if (llct > tlongline) tlongline = llct; - (void)printf(" %7ju", tlongline); + xo_emit(" {:long-lines/%7ju/%ju}", tlongline); } (void)close(fd); return (0); @@ -201,12 +214,13 @@ */ if (dochar || domulti) { if (fstat(fd, &sb)) { - warn("%s: fstat", file); + xo_warn("%s: fstat", file); (void)close(fd); return (1); } if (S_ISREG(sb.st_mode)) { - (void)printf(" %7lld", (long long)sb.st_size); + xo_emit(" {:characters/%7lld/%lld}", + (long long)sb.st_size); tcharct += sb.st_size; (void)close(fd); return (0); @@ -220,7 +234,7 @@ memset(&mbs, 0, sizeof(mbs)); while ((len = read(fd, buf, MAXBSIZE)) != 0) { if (len == -1) { - warn("%s: read", file); + xo_warn("%s: read", file); (void)close(fd); return (1); } @@ -233,7 +247,7 @@ (size_t)-1) { if (!warned) { errno = EILSEQ; - warn("%s", file); + xo_warn("%s", file); warned = 1; } memset(&mbs, 0, sizeof(mbs)); @@ -264,23 +278,23 @@ } if (domulti && MB_CUR_MAX > 1) if (mbrtowc(NULL, NULL, 0, &mbs) == (size_t)-1 && !warned) - warn("%s", file); + xo_warn("%s", file); if (doline) { tlinect += linect; - (void)printf(" %7ju", linect); + xo_emit(" {:lines/%7ju/%ju}", linect); } if (doword) { twordct += wordct; - (void)printf(" %7ju", wordct); + xo_emit(" {:words/%7ju/%ju}", wordct); } if (dochar || domulti) { tcharct += charct; - (void)printf(" %7ju", charct); + xo_emit(" {:characters/%7ju/%ju}", charct); } if (dolongline) { if (llct > tlongline) tlongline = llct; - (void)printf(" %7ju", llct); + xo_emit(" {:long-lines/%7ju/%ju}", llct); } (void)close(fd); return (0); @@ -289,6 +303,6 @@ static void usage() { - (void)fprintf(stderr, "usage: wc [-Lclmw] [file ...]\n"); + xo_error("usage: wc [-Lclmw] [file ...]\n"); exit(1); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201407310907.s6V97Qsw092908>