From owner-svn-src-all@freebsd.org Wed Jul 15 08:01:21 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 965EF9A292C; Wed, 15 Jul 2015 08:01:21 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from mail104.syd.optusnet.com.au (mail104.syd.optusnet.com.au [211.29.132.246]) by mx1.freebsd.org (Postfix) with ESMTP id 04B281EC5; Wed, 15 Jul 2015 08:01:20 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from c211-30-166-197.carlnfd1.nsw.optusnet.com.au (c211-30-166-197.carlnfd1.nsw.optusnet.com.au [211.30.166.197]) by mail104.syd.optusnet.com.au (Postfix) with ESMTPS id 0118C427D4A; Wed, 15 Jul 2015 18:01:13 +1000 (AEST) Date: Wed, 15 Jul 2015 18:01:12 +1000 (EST) From: Bruce Evans X-X-Sender: bde@besplex.bde.org To: Ian Lepore cc: d@delphij.net, Garrett Cooper , Baptiste Daroussin , src-committers , svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r285552 - head/usr.bin/xargs In-Reply-To: <1436912270.1334.309.camel@freebsd.org> Message-ID: <20150715152233.S934@besplex.bde.org> References: <201507141916.t6EJGEG1083928@repo.freebsd.org> <48222CD1-7087-4C9A-A586-71F6A37A601C@gmail.com> <55A574BA.4090700@delphij.net> <1436912270.1334.309.camel@freebsd.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed X-Optus-CM-Score: 0 X-Optus-CM-Analysis: v=2.1 cv=ItbjC+Lg c=1 sm=1 tr=0 a=KA6XNC2GZCFrdESI5ZmdjQ==:117 a=PO7r1zJSAAAA:8 a=JzwRw_2MAAAA:8 a=kj9zAlcOel0A:10 a=6I5d2MoRAAAA:8 a=I-3w-4To1FASnUU9HwgA:9 a=CjuIK1q_8ugA:10 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 15 Jul 2015 08:01:21 -0000 On Tue, 14 Jul 2015, Ian Lepore wrote: > On Tue, 2015-07-14 at 13:44 -0700, Xin Li wrote: >> On 07/14/15 13:29, Garrett Cooper wrote: >>> On Jul 14, 2015, at 12:16, Baptiste Daroussin >>> wrote: >>> >>>> Author: bapt Date: Tue Jul 14 19:16:14 2015 New Revision: 285552 >>>> URL: https://svnweb.freebsd.org/changeset/base/285552 >>>> >>>> Log: Convert atoi(3) to stronum(3) which allows to arguments and >>>> report proper errors to the users >>> >>> Is strtonum preferred over strtoll, etc? No, but it is better than atoi() and expand_number() (except it uses the long long abomination, like strtoll()). >> strtonum(3) is a wrapper of strtoll() and provides more functionality >> like range checking, so I think the answer would be yes. It intentionally provides less functionality except for the range checking, so as to try to be easier to use. > Except if we convert all our tools that take numbers on the command line > to use strtonum() then peoples' existing scripts and other automation > that passes 0xWhatever numbers suddenly stop working. strtonum() seems > to be about 2/3 of a good idea. 1/3 io a good idea. Bugs in it start with its name: - it uses the reserved namespace - it uses up a good name for a bad API Bugs in its API include too much weakening of strtol(), etc: - no support for bases other than 10. This is the most annoying one. With the strtol() family, you get this support automatically by not forcing base 10. Changing the type requires using another member of the strtol() family. That is still possible with strtonum() by just not using it in complicated cases. - no support for unsigned numbers - no support for a mixture of signed and unsigned numbers (with e.g. a signed lower limit and an unsigned upper limit). This can be built out of strtoul() but is complicated. Applications like dd need this. - no support for floating point. Most numbers can be represented using floating point, support for floating point is not wanted for an atoi() replacement, and extra args to specify the format are also not wanted. - no support even for large signed numbers. The API hasn't caught up with C99 yet. It uses the long long abomination instead of intmax_t. This is the most annoying design error. With the strtol() family, you get intmax_t support automatically by using strtoimax() for everything, However, error handling is slightly more complicated with the general type. BTW, it is unclear if POSIX even allows non-decimal or large args in utilities, even in ones like dd where natural arg values are multiples of powers of 2. Portable shell scripts certainly shouldn't use large non-decimal args. This is a bug in POSIX. Other bugs in its API include it being quite complicated to use despite one of its reasons for existence being to be easier to use than the strtol() family. A drop-in replacement for atoi() would probably be named xatoi() and do the same as atoi() except print a message and exit on error. (The behaviour of atoi() on error is only undefined in some cases, so atoi() cannot exit on all errors.) The message for this cannot be context-specific, so xatoi() can't handle errors as well as a program that actually checks for errors from atoi(). (The value of errno after an error is unspecified, so checking it is nonsense, but the nonsense usually works.) strtonum()'s unease of use starts with the existence of its errstr parameter. This parameter is a bit like strtol()'s endptr parameter. Often you don't need this parameter and have to fill it in with NULL or a dummy pointer. Actually using it requires further complications. Unease of use continues with strtonum() having the same problem as xatoi() with generating a context-specific errror messages. strtonum() can and does only return an error string that depends only on the error type. This string is quite short (shorter than ones returned by strerror()). strtonum() also sets errno. Unfortunately, errno alone is not enough to encode the error type, since the ERANGE errno must be split into 2 types. strtonum() has its errstr to do little more than this splitting. Then to actually use errstr, you have to either accept its error description or parse it to turn it into your context-specific description. The latter would take more code than using strtol() directly. My main idea for a better API is a variadic one where only one parameter other than the string is required: intmax_t strtonum(const char *nptr, const char *flags, ...) where the usual case is simple but the general one is complicated. The simplest case has flags "" and no more args. This might give xatoi(). The next level of complications is to either tell strtonum() the messages that it should print before exiting, or tell it to return an error string or code that is easy to print yourself before existing. It seems difficult to do either of these without large code that would lose most of the advantages of the wrapper. Bruce