From owner-freebsd-arch@FreeBSD.ORG Thu Jul 31 09:08:06 2014 Return-Path: Delivered-To: freebsd-arch@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 3294E63A; Thu, 31 Jul 2014 09:08:06 +0000 (UTC) Received: from na01-by2-obe.outbound.protection.outlook.com (mail-by2lp0242.outbound.protection.outlook.com [207.46.163.242]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (Client CN "mail.protection.outlook.com", Issuer "MSIT Machine Auth CA 2" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 454F62D7C; Thu, 31 Jul 2014 09:08:05 +0000 (UTC) Received: from BY2PR05CA043.namprd05.prod.outlook.com (10.141.250.33) by BLUPR05MB722.namprd05.prod.outlook.com (10.141.207.150) with Microsoft SMTP Server (TLS) id 15.0.995.14; Thu, 31 Jul 2014 09:08:03 +0000 Received: from BL2FFO11FD023.protection.gbl (2a01:111:f400:7c09::176) by BY2PR05CA043.outlook.office365.com (2a01:111:e400:2c5f::33) with Microsoft SMTP Server (TLS) id 15.0.995.14 via Frontend Transport; Thu, 31 Jul 2014 09:08:02 +0000 Received: from P-EMF02-SAC.jnpr.net (66.129.239.16) by BL2FFO11FD023.mail.protection.outlook.com (10.173.161.102) with Microsoft SMTP Server (TLS) id 15.0.990.10 via Frontend Transport; Thu, 31 Jul 2014 09:08:02 +0000 Received: from magenta.juniper.net (172.17.27.123) by P-EMF02-SAC.jnpr.net (172.24.192.21) with Microsoft SMTP Server (TLS) id 14.3.146.0; Thu, 31 Jul 2014 02:08:01 -0700 Received: from idle.juniper.net (idleski.juniper.net [172.25.4.26]) by magenta.juniper.net (8.11.3/8.11.3) with ESMTP id s6V97tn41852; Thu, 31 Jul 2014 02:07:55 -0700 (PDT) (envelope-from phil@juniper.net) Received: from idle.juniper.net (localhost [127.0.0.1]) by idle.juniper.net (8.14.4/8.14.3) with ESMTP id s6V97Qsw092908; Thu, 31 Jul 2014 05:07:41 -0400 (EDT) (envelope-from phil@idle.juniper.net) Message-ID: <201407310907.s6V97Qsw092908@idle.juniper.net> To: "Simon J. Gerraty" Subject: Re: XML Output: libxo - provide single API to output TXT, XML, JSON and HTML In-Reply-To: <20140730235123.AC944580A2@chaos.jnpr.net> Date: Thu, 31 Jul 2014 05:07:26 -0400 From: Phil Shafer MIME-Version: 1.0 Content-Type: text/plain X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:66.129.239.16; CTRY:US; IPV:NLI; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(6009001)(377424004)(164054003)(189002)(199002)(54356999)(81342001)(74662001)(99396002)(102836001)(21056001)(64706001)(86362001)(110136001)(50986999)(74502001)(107046002)(20776003)(47776003)(31966008)(80022001)(48376002)(97736001)(76482001)(81542001)(77982001)(50466002)(15202345003)(84676001)(53416004)(103666002)(83322001)(105596002)(69596002)(44976005)(1941001)(106466001)(92726001)(19580395003)(46102001)(15975445006)(85306003)(79102001)(68736004)(6806004)(81156004)(83072002)(4396001)(85852003)(76506005)(95666004)(87936001)(92566001); DIR:OUT; SFP:; SCL:1; SRVR:BLUPR05MB722; H:P-EMF02-SAC.jnpr.net; FPR:; MLV:sfv; PTR:InfoDomainNonexistent; MX:1; LANG:en; X-Microsoft-Antispam: BCL:0;PCL:0;RULEID: X-Forefront-PRVS: 0289B6431E Received-SPF: SoftFail (protection.outlook.com: domain of transitioning juniper.net discourages use of 66.129.239.16 as permitted sender) Authentication-Results: spf=softfail (sender IP is 66.129.239.16) smtp.mailfrom=phil@juniper.net; X-OriginatorOrg: juniper.net Cc: Alfred Perlstein , freebsd-arch@freebsd.org X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 31 Jul 2014 09:08:06 -0000 "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: 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 bear brown angry 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 #include #include +#include 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); }