From: "Tim Van Holder" To: Subject: Re: [patch] Second draft: a64l and l64a Date: Mon, 4 Jun 2001 19:30:51 +0200 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) In-Reply-To: X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4133.2400 Importance: Normal Reply-To: djgpp-workers AT delorie DOT com Errors-To: nobody AT delorie DOT com X-Mailing-List: djgpp-workers AT delorie DOT com X-Unsubscribes-To: listserv AT delorie DOT com Precedence: bulk > > I've had problems before where patches couldn't be applied due to line > > breaks added by the mail agent, so I've taken to sending diffs as > > attachments if they're meant to be applied, instead of just reviewed. > > I was talking from the point of view of someone who needs to review the > patches, not apply them (don't you have write access to the CVS?) I see your point. And no, I do not have write access. > > > I'd think that interpreting the argument as an unsigned long would > > > produce reasonable results. > > I was talking about possibly changing the signatures to use unsigned > > long, but I suppose that simply treating them as such would be OK. > > Given that glibc does that as well, it sounds plausible. I've made that change. > > > > + printf ("a64l(\"EliRules!\") -> %ld\n", > a64l("EliRules!")); > > > > > > This line has a bug in it. > > > > Hmmm - where exactly? I see nothing wrong with it :-) > > The missing smiley. > Changed it to "Rhubarb!" instead - that needs no smiley and also tests the overflow case :-) Third draft follows: diff -rN emptydir/a64l.c src/libc/posix/stdlib/a64l.c 0a1,38 > /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ > > #include > #include > #include > > long > a64l(const char* s) > { > int i = 0; > unsigned long value = 0; > > if (s == NULL || *s == '\0') > return 0L; > > for (i = 0; i < 6; ++i, ++s) > { > if (*s == '\0') > break; > /* Detect overflow; return the conversion of '/2BIG/' */ > if (value > (ULONG_MAX >> 6)) > return 1144341633L; > value <<= 6; > if (*s == '.') /* 0 */ > value += 0; > else if (*s == '/') /* 1 */ > ++value; > else if (*s >= '0' && *s <= '9') /* 2-11 */ > value += (*s - '0') + 2; > else if (*s >= 'A' && *s <= 'Z') /* 12-37 */ > value += (*s - 'A') + 12; > else if (*s >= 'a' && *s <= 'z') /* 38-63 */ > value += (*s - 'a') + 38; > else /* invalid digit */ > return 0L; > } > return (long) value; > } diff -rN emptydir/a64l.txh src/libc/posix/stdlib/a64l.txh 0a1,36 > @node a64l, string > @subheading Syntax > > @example > #include > > long a64l(const char *s); > @end example > > @subheading Description > > This function takes a pointer to a radix-64 representation, with the > first digit the least significant, and returns the corresponding > @code{long} value. > > If @var{s} contains more than six characters, only the first six are > used. If the first six characters of @var{s} contain a null terminator, > only those characters before the null terminator are used. > @code{a64l()} will scan the string from left to right, with the least > significant digit on the left, decoding each character as a 6-bit radix-64 > number. > > For a description of the radix-64 representation, @ref{l64a}. > > @subheading Return Value > > Returns the @code{long} value resulting from the conversion of the contents > of @var{s}, or 0L if @var{s} is NULL, points to an empty string, or points > to an invalid string (i.e. one not generated by a previous call to > @code{l64a()}). If the result would overflow a signed long, the > conversion of @samp{/2BIG/} (1144341633L) is returned. > > @subheading Portability > > @portability !ansi, posix > @port-note Posix 1003.1-200x, not POSIX-1:1996 diff -rN emptydir/l64a.c src/libc/posix/stdlib/l64a.c 0a1,36 > /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ > > #include > #include > #include > > char* > l64a(long _value) > { > static char radix64[7] = { "" }; > char *s = radix64 + 5; > unsigned long value = (unsigned long) _value; > > memset (radix64, 0, sizeof radix64); > > if (value == 0) > return radix64; > > while (value && s >= radix64) > { > int digit = value & 0x3f; > value >>= 6; > > if (digit == 0) > *s-- = '.'; > else if (digit == 1) > *s-- = '/'; > else if (digit < 12) > *s-- = '0' + (digit - 2); > else if (digit < 38) > *s-- = 'A' + (digit - 12); > else > *s-- = 'a' + (digit - 38); > } > return ++s; > } diff -rN emptydir/l64a.txh src/libc/posix/stdlib/l64a.txh 0a1,42 > @node l64a, string > @subheading Syntax > > @example > #include > > char *l64a(long value); > @end example > > @subheading Description > > This function takes a @code{long} argument and returns a pointer to its > radix-64 representation. Negative numbers are not supported. > @c FIXME: Supporting negative values (or at least unsigned longs) seems > @c more logical; should we be POSIX-compliant here? > > @subheading Return Value > > A pointer to a static buffer containing the radix-64 representation of > @var{value}. Subsequent calls will overwrite the contents of this buffer. > If @var{value} is 0L, this function returns an empty string. > > @subheading Radix-64 > @cindex radix-64 > > The radix-64 @sc{ascii} representation is a notation whereby 32-bit integers > are represented by up to 6 @sc{ascii} characters; each character represents > a single radix-64 digit. Radix-64 refers to the fact that each digit in this > representation can take 64 different values. > If the @code{long} type is more than 32 bits in size, only the low-order > 32 bits are used. > The characters used to represent digits are @samp{.} (dot) for 0, @samp{/} > for 1, @samp{0} through @samp{9} for 2 to 11, @samp{A} through @samp{Z} for > 12 to 37, and @samp{a} through @samp{z} for 38 to 63. > > Note that this is @emph{not} the same encoding used by either uuencode or the > MIME base64 encoding. > > @subheading Portability > > @portability !ansi, posix > @port-note Posix 1003.1-200x, not POSIX-1:1996 diff -rN emptydir/makefile src/libc/posix/stdlib/makefile 0a1,7 > # Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details > > TOP=../.. > > SRC += a64l.c l64a.c > > include $(TOP)/../makefile.inc diff -rN emptydir/makefile tests/libc/posix/stdlib/makefile 0a1,5 > TOP=../.. > > SRC += radix64.c > > include $(TOP)/../makefile.inc diff -rN emptydir/radix64.c tests/libc/posix/stdlib/radix64.c 0a1,39 > #include > #include > > int > main(void) > { > printf ("a64l(\"/.\") -> %ld\n", a64l("/.")); > printf ("a64l(\"DJGPP\") -> %ld\n", a64l("DJGPP")); > printf ("a64l(\"/.Rules!\") -> %ld\n", a64l("/.Rules!")); > printf ("a64l(\"Rhubarb!\") -> %ld\n", a64l("Rhubarb!")); > printf ("a64l(NULL) -> %ld\n", a64l(NULL)); > printf ("a64l(\"\") -> %ld\n", a64l("")); > printf ("a64l(\"Not Radix64\") -> %ld\n", a64l("Not Radix64")); > > printf ("a64l(l64a(1234)) -> %ld\n", a64l(l64a(1234))); > printf ("a64l(l64a(64)) -> %ld\n", a64l(l64a(64))); > printf ("a64l(l64a(7)) -> %ld\n", a64l(l64a(7))); > printf ("a64l(l64a(0)) -> %ld\n", a64l(l64a(0))); > printf ("a64l(l64a(-88)) -> %ld\n", a64l(l64a(-88))); > /* 0x54534554 is the binary representation of 'TEST' */ > printf ("a64l(l64a(0x54534554)) -> 0x%lx\n", a64l(l64a(0x54534554))); > > printf ("l64a(1234) -> '%s'\n", l64a(1234)); > printf ("l64a(64) -> '%s'\n", l64a(64)); > printf ("l64a(7) -> '%s'\n", l64a(7)); > printf ("l64a(0) -> '%s'\n", l64a(0)); > printf ("l64a(-88) -> '%s'\n", l64a(-88)); > printf ("l64a(0x54534554) -> '%s'\n", l64a(0x54534554)); > > printf ("l64a(a64l(\"/.\")) -> '%s'\n", l64a(a64l("/."))); > printf ("l64a(a64l(\"DJGPP\")) -> '%s'\n", l64a(a64l("DJGPP"))); > printf ("l64a(a64l(\"/.Rules!\")) -> '%s'\n", l64a(a64l("/.Rules!"))); > printf ("l64a(a64l(\"Rhubarb!\")) -> '%s'\n", l64a(a64l("Rhubarb!"))); > printf ("l64a(a64l(NULL)) -> '%s'\n", l64a(a64l(NULL))); > printf ("l64a(a64l(\"\")) -> '%s'\n", l64a(a64l(""))); > printf ("l64a(a64l(\"Not Radix64\")) -> '%s'\n", l64a(a64l("Not Radix64"))); > > return 0; > }