From owner-freebsd-standards Sun Feb 10 10: 2: 2 2002 Delivered-To: freebsd-standards@freebsd.org Received: from gate.sim.ionidea.com (ion.so-com.net [212.110.132.83]) by hub.freebsd.org (Postfix) with ESMTP id 2730737B402 for ; Sun, 10 Feb 2002 10:01:41 -0800 (PST) Received: (from phantom@localhost) by gate.sim.ionidea.com (8.11.6/8.11.1) id g1AI9Ee96853; Sun, 10 Feb 2002 20:09:14 +0200 (EET) (envelope-from phantom) Date: Sun, 10 Feb 2002 20:09:13 +0200 From: Alexey Zelkin To: standards@freebsd.org Subject: generalized "\'" flag support for vfprintf() (for both decimal and float numbers) Message-ID: <20020210200913.A96833@gate.sim.ionidea.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.3.20i X-Operating-System: FreeBSD 4.2-RELEASE i386 Sender: owner-freebsd-standards@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG hi, Heh, just finished it and it passed my basic tests. Tommorow I'll go with its cleanup, but anyway it would be interesting to listen opinions on the way how it's done. Index: vfprintf.c =================================================================== RCS file: /home/cvs/freebsd/src/lib/libc/stdio/vfprintf.c,v retrieving revision 1.36 diff -u -r1.36 vfprintf.c --- vfprintf.c 17 Dec 2001 15:11:29 -0000 1.36 +++ vfprintf.c 10 Feb 2002 18:04:30 -0000 @@ -114,12 +114,11 @@ static int __sprint __P((FILE *, struct __suio *)); static int __sbprintf __P((FILE *, const char *, va_list)) __printflike(2, 0); -static char *__ujtoa __P((uintmax_t, char *, int, int, char *, int, - char, const char *)); -static char *__ultoa __P((u_long, char *, int, int, char *, int, - char, const char *)); +static char *__ujtoa __P((uintmax_t, char *, int, int, char *)); +static char *__ultoa __P((u_long, char *, int, int, char *)); static void __find_arguments __P((const char *, va_list, union arg **)); static void __grow_type_table __P((int, enum typeid **, int *)); +static int __do_grouping __P((char *buf, char **cp, int size, int safety)); /* * Flush out all the vectors defined by the given uio, @@ -186,12 +185,10 @@ * use the given digits. */ static char * -__ultoa(u_long val, char *endp, int base, int octzero, char *xdigs, - int needgrp, char thousep, const char *grp) +__ultoa(u_long val, char *endp, int base, int octzero, char *xdigs) { register char *cp = endp; register long sval; - int ndig; /* * Handle the three cases separately, in the hope of getting @@ -203,7 +200,6 @@ *--cp = to_char(val); return (cp); } - ndig = 0; /* * On many machines, unsigned arithmetic is harder than * signed arithmetic, so we do at most one unsigned mod and @@ -212,29 +208,11 @@ */ if (val > LONG_MAX) { *--cp = to_char(val % 10); - ndig++; sval = val / 10; } else sval = val; do { *--cp = to_char(sval % 10); - ndig++; - /* - * If (*grp == CHAR_MAX) then no more grouping - * should be performed. - */ - if (needgrp && ndig == *grp && *grp != CHAR_MAX - && sval > 9) { - *--cp = thousep; - ndig = 0; - /* - * If (*(grp+1) == '\0') then we have to - * use *grp character (last grouping rule) - * for all next cases - */ - if (*(grp+1) != '\0') - grp++; - } sval /= 10; } while (sval != 0); break; @@ -263,50 +241,28 @@ /* Identical to __ultoa, but for intmax_t. */ static char * -__ujtoa(uintmax_t val, char *endp, int base, int octzero, char *xdigs, - int needgrp, char thousep, const char *grp) +__ujtoa(uintmax_t val, char *endp, int base, int octzero, char *xdigs) { char *cp = endp; intmax_t sval; - int ndig; /* quick test for small values; __ultoa is typically much faster */ /* (perhaps instead we should run until small, then call __ultoa?) */ if (val <= ULONG_MAX) - return (__ultoa((u_long)val, endp, base, octzero, xdigs, - needgrp, thousep, grp)); + return (__ultoa((u_long)val, endp, base, octzero, xdigs)); switch (base) { case 10: if (val < 10) { *--cp = to_char(val % 10); return (cp); } - ndig = 0; if (val > INTMAX_MAX) { *--cp = to_char(val % 10); - ndig++; sval = val / 10; } else sval = val; do { *--cp = to_char(sval % 10); - ndig++; - /* - * If (*grp == CHAR_MAX) then no more grouping - * should be performed. - */ - if (needgrp && *grp != CHAR_MAX && ndig == *grp - && sval > 9) { - *--cp = thousep; - ndig = 0; - /* - * If (*(grp+1) == '\0') then we have to - * use *grp character (last grouping rule) - * for all next cases - */ - if (*(grp+1) != '\0') - grp++; - } sval /= 10; } while (sval != 0); break; @@ -400,8 +356,6 @@ int width; /* width from format (%8d), or 0 */ int prec; /* precision from format (%.3d), or -1 */ char sign; /* sign prefix (' ', '+', '-', or \0) */ - char thousands_sep; /* locale specific thousands separator */ - const char *grouping; /* locale specific numeric grouping rules */ #ifdef FLOATING_POINT char *decimal_point; /* locale specific decimal point */ char softsign; /* temporary negative sign for floats */ @@ -532,8 +486,6 @@ } - thousands_sep = '\0'; - grouping = NULL; #ifdef FLOATING_POINT dtoaresult = NULL; decimal_point = localeconv()->decimal_point; @@ -614,8 +566,6 @@ goto rflag; case '\'': flags |= GROUPING; - thousands_sep = *(localeconv()->thousands_sep); - grouping = localeconv()->grouping; goto rflag; case '.': if ((ch = *fmt++) == '*') { @@ -750,6 +700,7 @@ else cp = "inf"; size = 3; + flags &= ~GROUPING; break; } if (isnan(_double)) { @@ -758,6 +709,7 @@ else cp = "nan"; size = 3; + flags &= ~GROUPING; break; } flags |= FPT; @@ -912,15 +864,11 @@ if (flags & INTMAX_SIZE) { if (ujval != 0 || prec != 0) cp = __ujtoa(ujval, cp, base, - flags & ALT, xdigs, - flags & GROUPING, thousands_sep, - grouping); + flags & ALT, xdigs); } else { if (ulval != 0 || prec != 0) cp = __ultoa(ulval, cp, base, - flags & ALT, xdigs, - flags & GROUPING, thousands_sep, - grouping); + flags & ALT, xdigs); } size = buf + BUF - cp; break; @@ -981,9 +929,18 @@ /* leading zeroes from decimal precision */ PAD(dprec - size, zeroes); +#define DOGRP(PTR, SIZE, SAFETY) { \ + if (flags & GROUPING) { \ + n2 = __do_grouping(buf, &PTR, SIZE, SAFETY); \ + SIZE += n2; \ + realsz += n2; \ + } \ +} + /* the string or number proper */ #ifdef FLOATING_POINT if ((flags & FPT) == 0) { + DOGRP(cp, size, 0); PRINT(cp, size); } else { /* glue together f_p fragments */ if (ch >= 'f') { /* 'f' or 'g' */ @@ -1000,11 +957,13 @@ PAD(-expt, zeroes); PRINT(cp, ndig); } else if (expt >= ndig) { + DOGRP(cp, ndig, 0); PRINT(cp, ndig); PAD(expt - ndig, zeroes); if (flags & ALT) PRINT(decimal_point, 1); } else { + DOGRP(cp, expt, ndig-expt); PRINT(cp, expt); cp += expt; PRINT(decimal_point, 1); @@ -1026,6 +985,7 @@ } } #else + DOGRP(cp, size, 0); PRINT(cp, size); #endif /* left-adjusting padding (always blank) */ @@ -1387,6 +1347,64 @@ *typetable = newtable; *tablesize = newsize; +} + +/*- + * Reformat buffer to include grouping characters + * + * params: + * buf -- pointer to begining of the buffer + * cp -- address of pointer to actual adta + * size -- amount of characters to group + * safety -- amount of characters after (*cp+size) to preserve + * (post-decimal part of FPT number) + */ +static int +__do_grouping(char *buf, char **cp, int size, int safety) { + + char thousands_sep; + char *grouping; + char *ptr, *tp; + int ndig, proceed, result, n; + + grouping = localeconv()->grouping; + if (*grouping == CHAR_MAX) + return (0); + + thousands_sep = *(localeconv()->thousands_sep); + if (thousands_sep == '\0') + return (0); + + result = 0; + + /* assume that data is at the begin of buffer */ + /* NOTE: strings can't overlap since actual value can fill only 1/3 part of buffer */ + if (buf != *cp) { + memmove(buf, *cp, size+safety); + *cp = buf; + } + + ndig = 0; + proceed = 0; + ptr = (*cp + size); + while (proceed < size) { + if (*grouping <= ndig) { + memmove(ptr+1, ptr, proceed+result+safety); + *ptr = thousands_sep; + result++; + if (*(grouping+1) != '\0') + grouping++; + if (*grouping == CHAR_MAX) /* no more grouping */ + break; + ndig = 0; + } else { + ndig++; + proceed++; + ptr--; + } + } + + return (result); } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-standards" in the body of the message From owner-freebsd-standards Tue Feb 12 6:21:18 2002 Delivered-To: freebsd-standards@freebsd.org Received: from gate.sim.ionidea.com (ion.so-com.net [212.110.132.83]) by hub.freebsd.org (Postfix) with ESMTP id E11A137B404; Tue, 12 Feb 2002 06:20:10 -0800 (PST) Received: (from phantom@localhost) by gate.sim.ionidea.com (8.11.6/8.11.1) id g1CDAN208399; Tue, 12 Feb 2002 15:10:23 +0200 (EET) (envelope-from phantom) Date: Tue, 12 Feb 2002 15:10:23 +0200 From: Alexey Zelkin To: hackers@freebsd.org, fenner@freebsd.org, standards@freebsd.org Subject: CFR: printf grouping support for floats (%'f) Message-ID: <20020212151023.A8369@gate.sim.ionidea.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.3.20i X-Operating-System: FreeBSD 4.2-RELEASE i386 Sender: owner-freebsd-standards@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG hi, This patch fixes *printf() family routines to correctly handle grouping for both decimals and floats. Current version of printf() supports grouping for decimals only. Yes, I know it looks like more hackish way, so other opinions are welcome! Since printf() is widely used and quite important function I'd like to get as much comments as possible (optimizations, simplifications, others) Index: vfprintf.c =================================================================== RCS file: /home/cvs/freebsd/src/lib/libc/stdio/vfprintf.c,v retrieving revision 1.36 diff -u -r1.36 vfprintf.c --- vfprintf.c 17 Dec 2001 15:11:29 -0000 1.36 +++ vfprintf.c 12 Feb 2002 13:02:00 -0000 @@ -114,12 +114,11 @@ static int __sprint __P((FILE *, struct __suio *)); static int __sbprintf __P((FILE *, const char *, va_list)) __printflike(2, 0); -static char *__ujtoa __P((uintmax_t, char *, int, int, char *, int, - char, const char *)); -static char *__ultoa __P((u_long, char *, int, int, char *, int, - char, const char *)); +static char *__ujtoa __P((uintmax_t, char *, int, int, char *)); +static char *__ultoa __P((u_long, char *, int, int, char *)); static void __find_arguments __P((const char *, va_list, union arg **)); static void __grow_type_table __P((int, enum typeid **, int *)); +static int __do_grouping __P((char *, char **, int, int)); /* * Flush out all the vectors defined by the given uio, @@ -186,12 +185,10 @@ * use the given digits. */ static char * -__ultoa(u_long val, char *endp, int base, int octzero, char *xdigs, - int needgrp, char thousep, const char *grp) +__ultoa(u_long val, char *endp, int base, int octzero, char *xdigs) { register char *cp = endp; register long sval; - int ndig; /* * Handle the three cases separately, in the hope of getting @@ -203,7 +200,6 @@ *--cp = to_char(val); return (cp); } - ndig = 0; /* * On many machines, unsigned arithmetic is harder than * signed arithmetic, so we do at most one unsigned mod and @@ -212,29 +208,11 @@ */ if (val > LONG_MAX) { *--cp = to_char(val % 10); - ndig++; sval = val / 10; } else sval = val; do { *--cp = to_char(sval % 10); - ndig++; - /* - * If (*grp == CHAR_MAX) then no more grouping - * should be performed. - */ - if (needgrp && ndig == *grp && *grp != CHAR_MAX - && sval > 9) { - *--cp = thousep; - ndig = 0; - /* - * If (*(grp+1) == '\0') then we have to - * use *grp character (last grouping rule) - * for all next cases - */ - if (*(grp+1) != '\0') - grp++; - } sval /= 10; } while (sval != 0); break; @@ -263,50 +241,28 @@ /* Identical to __ultoa, but for intmax_t. */ static char * -__ujtoa(uintmax_t val, char *endp, int base, int octzero, char *xdigs, - int needgrp, char thousep, const char *grp) +__ujtoa(uintmax_t val, char *endp, int base, int octzero, char *xdigs) { char *cp = endp; intmax_t sval; - int ndig; /* quick test for small values; __ultoa is typically much faster */ /* (perhaps instead we should run until small, then call __ultoa?) */ if (val <= ULONG_MAX) - return (__ultoa((u_long)val, endp, base, octzero, xdigs, - needgrp, thousep, grp)); + return (__ultoa((u_long)val, endp, base, octzero, xdigs)); switch (base) { case 10: if (val < 10) { *--cp = to_char(val % 10); return (cp); } - ndig = 0; if (val > INTMAX_MAX) { *--cp = to_char(val % 10); - ndig++; sval = val / 10; } else sval = val; do { *--cp = to_char(sval % 10); - ndig++; - /* - * If (*grp == CHAR_MAX) then no more grouping - * should be performed. - */ - if (needgrp && *grp != CHAR_MAX && ndig == *grp - && sval > 9) { - *--cp = thousep; - ndig = 0; - /* - * If (*(grp+1) == '\0') then we have to - * use *grp character (last grouping rule) - * for all next cases - */ - if (*(grp+1) != '\0') - grp++; - } sval /= 10; } while (sval != 0); break; @@ -400,8 +356,6 @@ int width; /* width from format (%8d), or 0 */ int prec; /* precision from format (%.3d), or -1 */ char sign; /* sign prefix (' ', '+', '-', or \0) */ - char thousands_sep; /* locale specific thousands separator */ - const char *grouping; /* locale specific numeric grouping rules */ #ifdef FLOATING_POINT char *decimal_point; /* locale specific decimal point */ char softsign; /* temporary negative sign for floats */ @@ -532,8 +486,6 @@ } - thousands_sep = '\0'; - grouping = NULL; #ifdef FLOATING_POINT dtoaresult = NULL; decimal_point = localeconv()->decimal_point; @@ -614,8 +566,6 @@ goto rflag; case '\'': flags |= GROUPING; - thousands_sep = *(localeconv()->thousands_sep); - grouping = localeconv()->grouping; goto rflag; case '.': if ((ch = *fmt++) == '*') { @@ -750,6 +700,7 @@ else cp = "inf"; size = 3; + flags &= ~GROUPING; break; } if (isnan(_double)) { @@ -758,6 +709,7 @@ else cp = "nan"; size = 3; + flags &= ~GROUPING; break; } flags |= FPT; @@ -912,15 +864,11 @@ if (flags & INTMAX_SIZE) { if (ujval != 0 || prec != 0) cp = __ujtoa(ujval, cp, base, - flags & ALT, xdigs, - flags & GROUPING, thousands_sep, - grouping); + flags & ALT, xdigs); } else { if (ulval != 0 || prec != 0) cp = __ultoa(ulval, cp, base, - flags & ALT, xdigs, - flags & GROUPING, thousands_sep, - grouping); + flags & ALT, xdigs); } size = buf + BUF - cp; break; @@ -981,9 +929,29 @@ /* leading zeroes from decimal precision */ PAD(dprec - size, zeroes); +#define DOGRP0(PTR, RET, SIZE, SAFETY) { \ + RET = __do_grouping(buf, &PTR, SIZE, SAFETY); \ +} +#define DOGRP1(PTR, SIZE) { \ + if (flags & GROUPING) { \ + DOGRP0(PTR, n2, SIZE, 0); \ + SIZE += n2; \ + realsz += n2; \ + } \ +} +#define DOGRP2(PTR, SIZE1, SIZE2, SAFETY) { \ + if (flags & GROUPING) { \ + DOGRP0(PTR, n2, SIZE1, SAFETY); \ + SIZE1 += n2; \ + SIZE2 += n2; \ + realsz += n2; \ + } \ +} + /* the string or number proper */ #ifdef FLOATING_POINT if ((flags & FPT) == 0) { + DOGRP1(cp, size); PRINT(cp, size); } else { /* glue together f_p fragments */ if (ch >= 'f') { /* 'f' or 'g' */ @@ -1000,11 +968,13 @@ PAD(-expt, zeroes); PRINT(cp, ndig); } else if (expt >= ndig) { + DOGRP1(cp, ndig); PRINT(cp, ndig); PAD(expt - ndig, zeroes); if (flags & ALT) PRINT(decimal_point, 1); } else { + DOGRP2(cp, expt, ndig, ndig-expt); PRINT(cp, expt); cp += expt; PRINT(decimal_point, 1); @@ -1026,6 +996,7 @@ } } #else + DOGRP1(cp, size); PRINT(cp, size); #endif /* left-adjusting padding (always blank) */ @@ -1387,6 +1358,67 @@ *typetable = newtable; *tablesize = newsize; +} + +/*- + * Reformat buffer to include grouping characters + * + * params: + * buf -- pointer to begining of the buffer + * cp -- address of pointer to actual adta + * size -- amount of characters to group + * safety -- amount of characters after (*cp+size) to preserve + * (post-decimal part of FPT number) + */ +static int +__do_grouping(char *buf, char **cp, int size, int safety) { + + char thousands_sep; + char *grouping; + char *ptr, *tp; + int ndig, proceed, result, n; + + /* XXX: return value of __dtoa() *possibly* *may* overflow size + * of internal buffer. Check this situation later. + */ + + grouping = localeconv()->grouping; + if (*grouping == CHAR_MAX) + return (0); + + thousands_sep = *(localeconv()->thousands_sep); + if (thousands_sep == '\0') + return (0); + + result = 0; + + /* make sure that data is at the begin of the buffer */ + if (buf != *cp) { + memmove(buf, *cp, size+safety); + *cp = buf; + } + + ndig = 0; + proceed = 0; + ptr = (*cp + size); + while (proceed < size) { + if (*grouping <= ndig) { + memmove(ptr+1, ptr, proceed+result+safety); + *ptr = thousands_sep; + result++; + if (*(grouping+1) != '\0') + grouping++; + if (*grouping == CHAR_MAX) /* no more grouping */ + break; + ndig = 0; + } else { + ndig++; + proceed++; + ptr--; + } + } + + return (result); } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-standards" in the body of the message From owner-freebsd-standards Tue Feb 12 14: 8:48 2002 Delivered-To: freebsd-standards@freebsd.org Received: from espresso.q9media.com (espresso.q9media.com [216.254.138.122]) by hub.freebsd.org (Postfix) with ESMTP id DBC2537B405 for ; Tue, 12 Feb 2002 14:07:30 -0800 (PST) Received: (from mike@localhost) by espresso.q9media.com (8.11.6/8.11.6) id g1CM33O02997; Tue, 12 Feb 2002 17:03:03 -0500 (EST) (envelope-from mike) Date: Tue, 12 Feb 2002 17:03:03 -0500 From: Mike Barcroft To: Chuck Rouillard Cc: FreeBSD-Standards Subject: Re: pathchk - review Message-ID: <20020212170303.B55750@espresso.q9media.com> References: <20020129210829.GC50337@madman.nectar.cc> <20020205232519.N7805-101000@opus.sandiegoca.ncr.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20020205232519.N7805-101000@opus.sandiegoca.ncr.com>; from chuckr@opus.sandiegoca.ncr.com on Tue, Feb 05, 2002 at 11:54:26PM -0800 Organization: The FreeBSD Project Sender: owner-freebsd-standards@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG Chuck Rouillard writes: > A revised `pathchk' is being submitted for review. Sorry for the delay in my review. > Makefile: `# $FreeBSD$' is needed here. > PROG= pathchk > > .include > pathchk.1: > .\" Copyright (c) 2001, 2002 Chuck Rouillard > .\" All rights reserved. > .\" > .\" Redistribution and use in source and binary forms, with or without > .\" modification, are permitted provided that the following conditions > .\" are met: > .\" 1. Redistributions of source code must retain the above copyright > .\" notice, this list of conditions and the following disclaimer. > .\" 2. Redistributions in binary form must reproduce the above copyright > .\" notice, this list of conditions and the following disclaimer in the > .\" documentation and/or other materials provided with the distribution. > .\" 3. The name of the author may not be used to endorse or promote > .\" products derived from this software without specific prior written > .\" permission. > .\" > .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS > .\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED > .\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY > .\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > .\" SUCH DAMAGE. > .\" > .\" This line should be `.\" $FreeBSD$'. > .\" > .Dd January 2, 2002 This could be refreshed. :) > .Dt PATHCHK 1 > .Os > .Sh NAME > .Nm pathchk > .Nd checks pathnames > .Sh SYNOPSIS > .Nm pathchk > .Op Fl p > .Ar pathname > .Ar ... > .Sh DESCRIPTION > The > .Nm pathchk The `pathchk' argument here is redundent. I don't comment on this problem below. > utility verifies whether a specified > .Ar pathname > may be used to access or create a file without error. By default, New sentences need to begin on new lines. I don't comment on this problem below. > the overall path, and each > .Ar pathname > component, is checked against the underlying filesystem. Any of the > following errors will result in a message along with the offending > .Ar pathname > sent to stderr. > .Pp > .Bl -bullet > .It > The > .Ar pathname > is longer than the maximum defined by PATH_MAX for the underlying > filesystem. > .It > The > .Ar pathname > contains a path component longer than the maximum defined by NAME_MAX > for the underlying filesystem. > .It > A component of the > .Ar pathname > which is not searchable or inaccessable by the > underlying filesystem. > .It > Contains any character(s) which are invalid for the containing directory. > .El > .Pp > Any > .Ar pathname > containing a non-existent path component is not considered an error if > none of the remaining components nor the overall path length exceed the > maximums defined by the underlying filesystem. > .Pp > The options are as follows: > .Bl -tag -width indent > .It Fl p > Verify each > .Ar pathname > using portability checks instead of the underlying filesystem. Report > any of the following as errors to console. > .Pp > .Bl -bullet > .It > The > .Ar pathname > is longer than the maximum _POSIX_PATH_MAX. > .It > The > .Ar pathname > contains a path component longer than the maximum _POXIX_NAME_MAX. > .It > The > .Ar pathname > contains at least one character which is not in the set of A-Z, a-z, 0-9, I think these should be listed in individual .Dq macros. > `.'(period), `-'(hyphen), or `_'(underscore). The `-'(hyphen) may not be .Sq and .Pq should be used to here to wrap. > used as the first character of any path component. > .El > .El > .Pp `.Sh DIAGNOSTICS' needed here. > .Nm pathchk > exits 0 on success, 1 if an error occurred. The .Ex macro should be used here. > .Sh SEE ALSO > .Xr stat 2 , > .Xr pathconf 2 Misordered references. > .Sh STANDARDS > The > .Nm pathchk > utility is expected to conform to > .St -susv2 > and > .St -p1003.2 . I think this should be SUSv3 and not refer to POSIX.2. You may want to have Ruslan review this too. I don't have a lot of mdoc-fu. > pathchk.c > /* > * Copyright (c) 2001, 2002 Chuck Rouillard > * All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions > * are met: > * 1. Redistributions of source code must retain the above copyright > * notice, this list of conditions and the following disclaimer. > * 2. Redistributions in binary form must reproduce the above copyright > * notice, this list of conditions and the following disclaimer in the > * documentation and/or other materials provided with the distribution. > * 3. The name of the author may not be used to endorse or promote > * products derived from this software without specific prior written > * permission. > * > * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS > * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED > * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY > * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > * SUCH DAMAGE. Needs a ` *' line and a ` * $FreeBSD$' line. > */ > #include > #include > > #include > #include > #include > #include > #include > #include > #include > > const char *illegalchar = "pathchk: Illegal character"; > const char *memoryerror = "pathchk: No memory to allocate"; > const char *nametoolong = "pathchk: Path component too long"; > const char *pathchkhelp = "usage: pathchk [-p] path ...\n"; > const char *pathtoolong = "pathchk: Pathname too long"; > const char *posix_chars = "0123456789._-" > "ABCDEFGHIJKLMNOPQRSTUVWXYZ" > "abcdefghijklmnopqrstuvwxyz"; These should all be #define's, unless I missed somewhere that they are changed. > /* > * Local function prototypes. > */ > int posixpath(char *); > int pe(const char *, int); > int systempath(char *); > void usage(void); These should all have `static' keywords. That will eliminate the need for the comment too. > > /* This line needs to be `/*-' to follow KNF, since you do special tabbing in this comment. See indent(1) for details. I don't comment on this below. > * Verify path portability by checking if the: > * - complete path and filename <= _POSIX_PATH_MAX, > * - each path component length <= _POSIX_NAME_MAX, > * - and that each path component contains no > * disallowed characters. > * Return 0 for an accepted path, 1 otherwise. > */ > int > posixpath(char *pathname) > { > int namelen, pathlen, rval; > char *name, *path; > char *wpath, *wptr; These two lines can be combined. I think pointers are generally considered to be larger than integers, so it might be a good idea to move the combined line to the top. > > pathlen = strlen(pathname); > if (pathlen > _POSIX_PATH_MAX) { > (void)fprintf(stderr, "%s\n%s\n", pathtoolong, pathname); > return 1; Return values need to be wrapped in parens. I don't comment on this below. > } > > /* > * Create space in which to build a validated Comment lines should be wrapped at 80 characters. I don't comment on this below. > * path. Upon any error, this path is shown > * in its current state. > */ > if ((path = malloc(pathlen + 1)) == NULL) { > (void)fprintf(stderr, "%s\n", memoryerror); > exit(1); I thought this was mentioned in a earlier review, but this should use err(1). Since the errno can provide a more traditional message or a locale-specific message (if we had support for that :). I don't comment on this below. Please use -style exit levels everywhere. > } > *path = NULL; > > /* > * Since `strsep' mangles the strings sent to it, > * create a working copy of pathname to preserve > * the original argument value. Note that an > * additional working pointer is set for use > * with `free'. > */ > if ((wpath = strdup(pathname)) == NULL) { > (void)fprintf(stderr, "%s\n", memoryerror); > exit(1); > } > wptr = wpath; > > /* > * Begin path validation by checking each path > * component for any exceeded length and any > * disallowed character(s). > */ > rval = 0; > while ((name = strsep(&wpath, "/")) != NULL) { > if ((namelen = strlen(name)) != 0) { > (void)strcat(path, name); Presumably `name' is guaranteed to fit into `path'? (I didn't check.) > if (namelen > _POSIX_NAME_MAX) { > (void)fprintf(stderr, "%s\n%s\n", > nametoolong, path); Wrapped lines begin four spaces further than the line above. See style(9) for details. I don't comment on this below. > rval = 1; > break; > } > if (*name == '-' || > strspn(name, posix_chars) != namelen) { > (void)fprintf(stderr, "%s\n%s\n", > illegalchar, path); > rval = 1; > break; > } > } > if (wpath != NULL) > (void)strcat(path, "/"); > } > free(wptr); > free(path); > return rval; > } > > /* > * Assume all error types are path errors except in the > * case where a path/file does not exist. > */ > int > pe(const char *path, int type) > { Need an extra line here. Specifically, functions that don't have local variables still put a blank space here. I don't comment on this below. > switch (type) { > case ENOENT: > return 0; > default: > perror("pathchk"); > (void)fprintf(stderr, "%s\n", path); > break; > } > return 1; > } > > /* > * Check the current pathname against the underlying > * filesystem for access, overall path length, and > * path component length. > * > * If the path component is a directory and is: > * - the last component : return 0 > * - not the last component but searchable : return 0 > * - last component, but not searchable : return 1 > * > * If the path component is a file and is: > * - the last component: return 0 > * - not the last component : return 1 > * > * If a path component (and conseqently the entire path > * from that point) is found to not exist, then only the > * overall path and each path component are checked for > * excessive length. > */ > int > systempath(char *pathname) > { > struct stat statbuf; > int namelen, namemax; > int pathlen, pathmax; > int pexist, rval; These three lines can be combined. > char *name, *path; > char *wpath, *wptr; These two lines can be combined. See comment above about pointers. > > /* > * Do an initial check to determine any critical > * errors and prime max values. > */ > pexist = 1; > path = *pathname == '/' ? "/" : "."; > namemax = pathconf(path , _PC_NAME_MAX); > pathmax = pathconf(path , _PC_PATH_MAX); I think pathconf(2)'s return value should be checked for error. I don't comment on this below. > if (namemax == -1 || pathmax == -1) { > if ((pexist = pe(pathname, errno)) == 1) > return 1; > } > > /* > * Create space in which to build a validated > * path. Upon any error, this path is shown > * in its current state. > */ > pathlen = strlen(pathname); > if ((path = malloc(pathlen + 1)) == NULL) { > (void)fprintf(stderr, "%s\n", memoryerror); > exit(1); > } > *path = NULL; > > /* > * Since `strsep' mangles the strings sent to it, This should probably say `strsep(3)'. > * create a working copy of pathname to preserve > * the original argument value. Note that an > * additional working pointer is set for use > * with `free'. > */ > if ((wpath = strdup(pathname)) == NULL) { > (void)fprintf(stderr, "%s\n", memoryerror); > exit(1); > } > wptr = wpath; > > /* > * Begin path validation by checking each path > * component for errors and reached maximums. Any > * error (except for non-existing paths) will end > * further testing and exit function. > */ > rval = 0; > while ((name = strsep(&wpath, "/")) != NULL) { > if ((namelen = strlen(name)) != 0) { > (void)strcat(path, name); > if (pexist) { > if (stat(path, &statbuf) == -1) { > /* > * Since stat failed, check errno and > * and show error to console -except- > * if the path doesn't exist (ENOENT). > */ > if ((pexist = pe(path, errno)) == 1) { > rval = 1; > break; > } > } else { > /* > * As long as the path is still valid, > * verify the allowable path length > * and path component maximums for > * the current filesystem. > */ > namemax = pathconf(path, _PC_NAME_MAX); > pathmax = pathconf(path, _PC_PATH_MAX); > if (namemax == -1 || pathmax == -1) { > if ((pexist = > pe(path, errno)) == 1) { > rval = 1; > break; > } > } > } > } else { > /* > * If the path doesn't exist, the only > * realistic checks are those based on > * overal path length and path component > * length. Maximums are based on last > * successful call to pathconf. > */ > if (namelen > namemax) { > (void)fprintf(stderr, "%s\n%s\n", > nametoolong, path); > rval = 1; > break; > } > if (pathlen > pathmax) { > (void)fprintf(stderr, "%s\n%s\n", > pathtoolong, path); > rval = 1; > break; > } > } > } > if (wpath != NULL) > (void)strcat(path, "/"); > } > free(wptr); > free(path); > return rval; > } > > void > usage(void) > { > (void)fprintf(stderr, "%s\n", pathchkhelp); > exit(1); > } > > int > main(int argc, char **argv) > { > int (*fptr)(); > int c, pflag, rval; > > pflag = rval = 0; > while ((c = getopt(argc, argv, "p")) != -1) { > switch (c) { > case 'p': > pflag = 1; > break; > case '?': > default: > usage(); > } > } > argc -= optind; > argv += optind; > if (argc == 0) > usage(); > fptr = (pflag == 0) ? systempath : posixpath; > while (argc--) > rval |= (fptr)(*argv++); > exit(rval); > } Best regards, Mike Barcroft To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-standards" in the body of the message From owner-freebsd-standards Tue Feb 12 14:32:20 2002 Delivered-To: freebsd-standards@freebsd.org Received: from opus.sandiegoca.ncr.com (tan7.ncr.com [192.127.94.7]) by hub.freebsd.org (Postfix) with ESMTP id 1912737B41D; Tue, 12 Feb 2002 14:32:12 -0800 (PST) Received: from localhost (chuckr@localhost) by opus.sandiegoca.ncr.com (8.11.6/8.11.6) with ESMTP id g1CMb3s22454; Tue, 12 Feb 2002 14:37:03 -0800 (PST) (envelope-from chuckr@opus.sandiegoca.ncr.com) Date: Tue, 12 Feb 2002 14:37:03 -0800 (PST) From: Chuck Rouillard X-X-Sender: To: Mike Barcroft Cc: FreeBSD-Standards Subject: Re: pathchk - review In-Reply-To: <20020212170303.B55750@espresso.q9media.com> Message-ID: <20020212143150.H22449-100000@localhost> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-standards@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG On Tue, 12 Feb 2002, Mike Barcroft wrote: > Chuck Rouillard writes: > > A revised `pathchk' is being submitted for review. > > Sorry for the delay in my review. Mike, it appears you grabbed an earlier version from the list. Nevertheless, some of your suggestions still apply (especially the man page). Thanks, .cr To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-standards" in the body of the message From owner-freebsd-standards Tue Feb 12 19:16:31 2002 Delivered-To: freebsd-standards@freebsd.org Received: from descent.robbins.dropbear.id.au (020.c.001.mel.iprimus.net.au [203.134.131.20]) by hub.freebsd.org (Postfix) with ESMTP id 5D33537B417 for ; Tue, 12 Feb 2002 19:16:25 -0800 (PST) Received: (from tim@localhost) by descent.robbins.dropbear.id.au (8.11.6/8.11.6) id g1D2xZj04306 for freebsd-standards@FreeBSD.ORG; Wed, 13 Feb 2002 13:59:35 +1100 (EST) (envelope-from tim) Date: Wed, 13 Feb 2002 13:59:35 +1100 From: Tim Robbins To: freebsd-standards@FreeBSD.ORG Subject: env(1) and P1003.2-1992 conformance Message-ID: <20020213135934.A4228@descent.robbins.dropbear.id.au> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5.1i Sender: owner-freebsd-standards@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG Here is a patch that corrects the exit status of the env utility to make it compatible with P1003.2-1992. OpenBSD and NetBSD exit with the right status (see NetBSD env.c revision 1.2 from 1993), FreeBSD does not. This really is a trivial change. Tim Index: env/env.c =================================================================== RCS file: /home/ncvs/src/usr.bin/env/env.c,v retrieving revision 1.5 diff -u -r1.5 env.c --- env/env.c 1999/08/27 08:59:31 1.5 +++ env/env.c 2002/02/13 02:50:49 @@ -42,6 +42,7 @@ #endif /* not lint */ #include +#include #include #include #include @@ -75,7 +76,7 @@ (void)setenv(*argv, ++p, 1); if (*argv) { execvp(*argv, argv); - err(1, "%s", *argv); + err(errno == ENOENT ? 127 : 126, "%s", *argv); } for (ep = environ; *ep; ep++) (void)printf("%s\n", *ep); Index: printenv/printenv.1 =================================================================== RCS file: /home/ncvs/src/usr.bin/printenv/printenv.1,v retrieving revision 1.11 diff -u -r1.11 printenv.1 --- printenv/printenv.1 2001/07/05 06:35:03 1.11 +++ printenv/printenv.1 2002/02/13 02:51:01 @@ -57,12 +57,6 @@ is specified, only its value is printed. .Pp -If a -.Ar name -is specified and it is not defined in the environment, -.Nm -returns exit status 1, else it returns status 0. -.Pp Some shells may provide a builtin .Nm command which is similar or identical to this utility. @@ -122,11 +116,24 @@ .Pa foo without the path, as well as set up the environment as desired. +.Sh DIAGNOSTICS +.Ex -std printenv +.Pp +.Ex -std env +The +.Nm env +utility exits 126 if the requested utility was found but +could not be executed and 127 if the utility could not be found. .Sh SEE ALSO .Xr csh 1 , .Xr sh 1 , .Xr execvp 3 , .Xr environ 7 +.Sh STANDARDS +The +.Nm env +utility is expected to be compatible with +.St -p1003.2-92 . .Sh HISTORY The .Nm To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-standards" in the body of the message From owner-freebsd-standards Tue Feb 12 21:16:53 2002 Delivered-To: freebsd-standards@freebsd.org Received: from descent.robbins.dropbear.id.au (018.a.009.mel.iprimus.net.au [210.50.112.18]) by hub.freebsd.org (Postfix) with ESMTP id B658A37B402 for ; Tue, 12 Feb 2002 21:16:39 -0800 (PST) Received: (from tim@localhost) by descent.robbins.dropbear.id.au (8.11.6/8.11.6) id g1D5GYo05003 for freebsd-standards@FreeBSD.ORG; Wed, 13 Feb 2002 16:16:34 +1100 (EST) (envelope-from tim) Date: Wed, 13 Feb 2002 16:16:34 +1100 From: Tim Robbins To: freebsd-standards@FreeBSD.ORG Subject: xargs(1) -E, -p options and exit status Message-ID: <20020213161634.A4626@descent.robbins.dropbear.id.au> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5.1i Sender: owner-freebsd-standards@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG This patch corrects the exit status of xargs as well as adds the P1003.1-2001 -E and -p options. I have not added -L and -I options because jmallett is already working on those. It's worth pointing out that the versions of xargs in -STABLE and -CURRENT are NOT POSIX.2 compliant as they claim. Revision 1.7 to xargs.c totally broke the documented 127 exit status by switching from vfork() to fork(). tim@descent$ echo 'hello' | xargs /no xargs: /no: No such file or directory tim@descent$ echo $? 1 Additionally, it would never exit 126 as required by P1003.2. Tim Index: xargs/xargs.1 =================================================================== RCS file: /home/ncvs/src/usr.bin/xargs/xargs.1,v retrieving revision 1.15 diff -u -r1.15 xargs.1 --- xargs/xargs.1 2001/07/05 08:51:08 1.15 +++ xargs/xargs.1 2002/02/13 05:15:34 @@ -44,14 +44,14 @@ .Nd "construct argument list(s) and execute utility" .Sh SYNOPSIS .Nm -.Op Fl 0 +.Op Fl 0pt +.Op Fl E Ar eofstr .Op Fl J Ar replstr .Oo .Fl n Ar number .Op Fl x .Oc .Op Fl s Ar size -.Op Fl t .Op Ar utility Op Ar argument ... .Sh DESCRIPTION The @@ -92,6 +92,10 @@ .Fl print0 function in .Xr find 1 . +.It Fl E Ar eofstr +Use +.Ar eofstr +as a logical EOF marker. .It Fl J Ar replstr If this option is specified, .Nm @@ -142,6 +146,13 @@ The current default value for .Ar number is 5000. +.It Fl p +Echo each command to be executed and ask the user whether it should be +executed. +A response of +.Ql y +causes the command to be executed, any other response causes it to be +skipped. .It Fl s Ar size Set the maximum number of bytes for the command line length provided to .Ar utility . @@ -184,15 +195,19 @@ .Ar utility cannot be invoked, an invocation of the utility is terminated by a signal or an invocation of the utility exits with a value of 255. -.Pp +.Sh DIAGNOSTICS The .Nm utility exits with a value of 0 if no error occurs. If +.Ar utility +cannot be found, +.Nm +exits with a value of 127, otherwise if .Ar utility -cannot be invoked, +cannot be executed, .Nm -exits with a value of 127. +exits with a value of 126. If any other error occurs, .Nm exits with a value of 1. Index: xargs/xargs.c =================================================================== RCS file: /home/ncvs/src/usr.bin/xargs/xargs.c,v retrieving revision 1.11 diff -u -r1.11 xargs.c --- xargs/xargs.c 2001/12/11 22:36:26 1.11 +++ xargs/xargs.c 2002/02/13 05:15:36 @@ -52,6 +52,7 @@ #include #include +#include #include #include #include @@ -59,7 +60,7 @@ #include "pathnames.h" -int tflag, rval; +int pflag, tflag, rval; int zflag; void run __P((char **)); @@ -74,14 +75,16 @@ { int ch; char *p, *bbp, **bxp, *ebp, **exp, **xp; - int cnt, jfound, indouble, insingle; + int cnt, jfound, indouble, insingle, foundeof; int nargs, nflag, nline, xflag, wasquoted; char **av, **avj, *argp, **ep, *replstr; + const char *eofstr; long arg_max; ep = env; jfound = 0; replstr = NULL; /* set if user requests -J */ + eofstr = ""; /* * POSIX.2 limits the exec line length to ARG_MAX - 2K. Running that @@ -105,8 +108,11 @@ nline -= strlen(*ep++) + 1 + sizeof(*ep); } nflag = xflag = wasquoted = 0; - while ((ch = getopt(argc, argv, "0J:n:s:tx")) != -1) + while ((ch = getopt(argc, argv, "0E:J:n:ps:tx")) != -1) switch(ch) { + case 'E': + eofstr = optarg; + break; case 'J': replstr = optarg; break; @@ -115,6 +121,9 @@ if ((nargs = atoi(optarg)) <= 0) errx(1, "illegal argument count"); break; + case 'p': + pflag = 1; + break; case 's': nline = atoi(optarg); break; @@ -216,8 +225,11 @@ errx(1, "unterminated quote"); arg2: + foundeof = *eofstr != '\0' && + strcmp(argp, eofstr) == 0; + /* Do not make empty args unless they are quoted */ - if (argp != p || wasquoted) { + if ((argp != p || wasquoted) && !foundeof) { *p++ = '\0'; *xp++ = argp; } @@ -227,7 +239,7 @@ * run the command. If xflag and max'd out on buffer * but not on args, object. */ - if (xp == exp || p > ebp || ch == EOF) { + if (xp == exp || p > ebp || ch == EOF || foundeof) { if (xflag && xp != exp && p > ebp) errx(1, "insufficient space for arguments"); if (jfound) { @@ -236,7 +248,7 @@ } *xp = NULL; run(av); - if (ch == EOF) + if (ch == EOF || foundeof) exit(rval); p = bbp; xp = bxp; @@ -296,34 +308,51 @@ run(argv) char **argv; { - volatile int noinvoke; char **p; + FILE *ttyfp; pid_t pid; - int status; + int ch, status, sverrno; - if (tflag) { + if (tflag || pflag) { (void)fprintf(stderr, "%s", *argv); for (p = argv + 1; *p; ++p) (void)fprintf(stderr, " %s", *p); - (void)fprintf(stderr, "\n"); - (void)fflush(stderr); + if (pflag) { + if ((ttyfp = fopen("/dev/tty", "r")) != NULL) { + (void)fprintf(stderr, "?"); + (void)fflush(stderr); + ch = getc(ttyfp); + fclose(ttyfp); + if (ch != 'y') + return; + } + } else { + (void)fprintf(stderr, "\n"); + (void)fflush(stderr); + } } - noinvoke = 0; switch(pid = fork()) { case -1: err(1, "fork"); case 0: execvp(argv[0], argv); + sverrno = errno; warn("%s", argv[0]); - noinvoke = 1; - _exit(1); + /* + * XXX Parent needs to know whether the utility couldn't be + * found, or if it was found but could not be invoked. + */ + _exit(sverrno == ENOENT ? 254 : 253); } pid = waitpid(pid, &status, 0); if (pid == -1) err(1, "waitpid"); - /* If we couldn't invoke the utility, exit 127. */ - if (noinvoke) + /* Exit 127 if the utility could not be found */ + if (WEXITSTATUS(status) == 254) exit(127); + /* Exit 126 if the utility was found but not could be invoked */ + if (WEXITSTATUS(status) == 253) + exit(126); /* If utility signaled or exited with a value of 255, exit 1-125. */ if (WIFSIGNALED(status) || WEXITSTATUS(status) == 255) exit(1); @@ -335,7 +364,7 @@ usage() { fprintf(stderr, - "usage: xargs [-0t] [-J replstr] [-n number [-x]] [-s size]\n" - " [utility [argument ...]]\n"); +"usage: xargs [-0pt] [-E eofstr] [-J replstr] [-n number [-x]] [-s size]\n" +" [utility [argument ...]]\n"); exit(1); } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-standards" in the body of the message From owner-freebsd-standards Sat Feb 16 18: 2:22 2002 Delivered-To: freebsd-standards@freebsd.org Received: from gw.nectar.cc (gw.nectar.cc [208.42.49.153]) by hub.freebsd.org (Postfix) with ESMTP id E895C37B405; Sat, 16 Feb 2002 18:02:18 -0800 (PST) Received: from madman.nectar.cc (madman.nectar.cc [10.0.1.111]) by gw.nectar.cc (Postfix) with ESMTP id 72DA836; Sat, 16 Feb 2002 20:02:18 -0600 (CST) Received: (from nectar@localhost) by madman.nectar.cc (8.11.6/8.11.6) id g1H22Ig46992; Sat, 16 Feb 2002 20:02:18 -0600 (CST) (envelope-from nectar) Date: Sat, 16 Feb 2002 20:02:18 -0600 From: "Jacques A. Vidrine" To: Mike Barcroft Cc: Chuck Rouillard , FreeBSD-Standards Subject: Re: pathchk - review Message-ID: <20020217020217.GB46829@madman.nectar.cc> Mail-Followup-To: "Jacques A. Vidrine" , Mike Barcroft , Chuck Rouillard , FreeBSD-Standards References: <20020129210829.GC50337@madman.nectar.cc> <20020205232519.N7805-101000@opus.sandiegoca.ncr.com> <20020212170303.B55750@espresso.q9media.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20020212170303.B55750@espresso.q9media.com> User-Agent: Mutt/1.3.27i X-Url: http://www.nectar.cc/ Sender: owner-freebsd-standards@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG On Tue, Feb 12, 2002 at 05:03:03PM -0500, Mike Barcroft wrote: > > const char *illegalchar = "pathchk: Illegal character"; > > const char *memoryerror = "pathchk: No memory to allocate"; > > const char *nametoolong = "pathchk: Path component too long"; > > const char *pathchkhelp = "usage: pathchk [-p] path ...\n"; > > const char *pathtoolong = "pathchk: Pathname too long"; > > const char *posix_chars = "0123456789._-" > > "ABCDEFGHIJKLMNOPQRSTUVWXYZ" > > "abcdefghijklmnopqrstuvwxyz"; > > These should all be #define's, Why? > unless I missed somewhere that they are > changed. They are const :-) Cheers, -- Jacques A. Vidrine http://www.nectar.cc/ NTT/Verio SME . FreeBSD UNIX . Heimdal Kerberos jvidrine@verio.net . nectar@FreeBSD.org . nectar@kth.se To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-standards" in the body of the message From owner-freebsd-standards Sat Feb 16 21:47:52 2002 Delivered-To: freebsd-standards@freebsd.org Received: from espresso.q9media.com (espresso.q9media.com [216.254.138.122]) by hub.freebsd.org (Postfix) with ESMTP id 3AA0A37B400; Sat, 16 Feb 2002 21:47:48 -0800 (PST) Received: (from mike@localhost) by espresso.q9media.com (8.11.6/8.11.6) id g1H5hdP11622; Sun, 17 Feb 2002 00:43:39 -0500 (EST) (envelope-from mike) Date: Sun, 17 Feb 2002 00:43:39 -0500 From: Mike Barcroft To: "Jacques A. Vidrine" Cc: Chuck Rouillard , FreeBSD-Standards Subject: Re: pathchk - review Message-ID: <20020217004339.J57687@espresso.q9media.com> References: <20020129210829.GC50337@madman.nectar.cc> <20020205232519.N7805-101000@opus.sandiegoca.ncr.com> <20020212170303.B55750@espresso.q9media.com> <20020217020217.GB46829@madman.nectar.cc> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20020217020217.GB46829@madman.nectar.cc>; from nectar@FreeBSD.ORG on Sat, Feb 16, 2002 at 08:02:18PM -0600 Organization: The FreeBSD Project Sender: owner-freebsd-standards@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG Jacques A. Vidrine writes: > On Tue, Feb 12, 2002 at 05:03:03PM -0500, Mike Barcroft wrote: > > > const char *illegalchar = "pathchk: Illegal character"; > > > const char *memoryerror = "pathchk: No memory to allocate"; > > > const char *nametoolong = "pathchk: Path component too long"; > > > const char *pathchkhelp = "usage: pathchk [-p] path ...\n"; > > > const char *pathtoolong = "pathchk: Pathname too long"; > > > const char *posix_chars = "0123456789._-" > > > "ABCDEFGHIJKLMNOPQRSTUVWXYZ" > > > "abcdefghijklmnopqrstuvwxyz"; > > > > These should all be #define's, > > Why? Here's part of a private discussion I had with the author regarding this: : My suggestion was mostly for making the code easier to read than for : optimization. It's much clearer that variables are read-only when : the variable name is in caps and the variable is actually a manifest : constant. > > unless I missed somewhere that they are > > changed. > > They are const :-) The type is a pointer to a read-only string. The type he was really looking for was a read-only pointer to a read-only string: const char * const VARIABLE; But as I suggested, manifest constants are better. Best regards, Mike Barcroft To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-standards" in the body of the message