Date: Thu, 1 Mar 2001 16:06:43 +0200 (IST) From: Eli Zaretskii X-Sender: eliz AT is To: Rafael García cc: djgpp AT delorie DOT com Subject: RE: atoi() with 8 bit chars In-Reply-To: <3a9e528a$1@filemon.telecable.es> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=ISO-8859-1 Reply-To: djgpp AT delorie DOT com Errors-To: nobody AT delorie DOT com X-Mailing-List: djgpp AT delorie DOT com X-Unsubscribes-To: listserv AT delorie DOT com Precedence: bulk On Thu, 1 Mar 2001, Rafael Garc=EDa wrote: > > It's a bug in the library; thanks for reporting it. Here's a patch > > for the strtol function which is responsible for this bug: > > ......... >=20 > I don't know how to aply that. I only have binary version of the compiler= . The patch is for the library, not for the compiler. All you need to do is download v2/djlsr203.zip (1.5MB), extract strtol.c=20 from there, apply the patch to it, compile it, and put it into libc.a. =20 The DJGPP FAQ explains how to do that in section 21.4. I am attaching=20 below a patched version of strtol.c, so that you could bypass the first=20 step entirely. > Nor I am interested in substitute all the compiler instalations I can use= . Are you interested in having a library that can be trusted? The version=20 of strtol below was thoroughly tested and improved over the years. While= =20 you did find a bug there, feeding 8-bit characters to strtol is not a=20 very frequent operation; most of the time, strtol and atoi have to deal with numeric strings, and the library version works very well for those,=20 including some very difficult and subtle cases (take a look at the source= =20 below, and you will see it). > #undef atol // now I have to call original ones > #undef atoi > #undef strtol >=20 > long myatol(const char *s) { > while (isspace(*s)) s++; > if (*s & 0x80) return 0; > else return atol(s); > } This will not work reliably, because some library functions call strtol=20 internally. They will bypass these macros. > 1) How can I remove "assignment discards qualifiers from pointer target > type" warning at > "*endp=3Ds" line? Use `unconst'. See the source below for an example. > 2) Is it possible to know library version, to not use this patch when not > necessary?... > Something like #if defined(__DJGPP__) && (__DJGPPVER__ #include #include #include #include long strtol(const char *nptr, char **endptr, int base) { const char *s =3D nptr; unsigned long acc; int c; unsigned long cutoff; int neg =3D 0, any, cutlim; /* * Skip white space and pick up leading +/- sign if any. * If base is 0, allow 0x for hex and 0 for octal, else * assume decimal; if base is already 16, allow 0x. */ do { c =3D *s++; } while (isspace(c & 0xff)); if (c =3D=3D '-') { neg =3D 1; c =3D *s++; } else if (c =3D=3D '+') c =3D *s++; if ((base =3D=3D 0 || base =3D=3D 16) && c =3D=3D '0' && (*s =3D=3D 'x' || *s =3D=3D 'X')) { c =3D s[1]; s +=3D 2; base =3D 16; } if (base =3D=3D 0) base =3D c =3D=3D '0' ? 8 : 10; /* * Compute the cutoff value between legal numbers and illegal * numbers. That is the largest legal value, divided by the * base. An input number that is greater than this value, if * followed by a legal input character, is too big. One that * is equal to this value may be valid or not; the limit * between valid and invalid numbers is then based on the last * digit. For instance, if the range for longs is * [-2147483648..2147483647] and the input base is 10, * cutoff will be set to 214748364 and cutlim to either * 7 (neg=3D=3D0) or 8 (neg=3D=3D1), meaning that if we have accumulated * a value > 214748364, or equal but the next digit is > 7 (or 8), * the number is too big, and we will return a range error. * * Set any if any `digits' consumed; make it negative to indicate * overflow. */ cutoff =3D neg ? -(unsigned long)LONG_MIN : LONG_MAX; cutlim =3D cutoff % (unsigned long)base; cutoff /=3D (unsigned long)base; for (acc =3D 0, any =3D 0, c &=3D 0xff;; c =3D *s++, c &=3D 0xff) { if (isdigit(c)) c -=3D '0'; else if (isalpha(c)) c -=3D isupper(c) ? 'A' - 10 : 'a' - 10; else break; if (c >=3D base) break; if (any < 0 || acc > cutoff || (acc =3D=3D cutoff && c > cutlim)) any =3D -1; else { any =3D 1; acc *=3D base; acc +=3D c; } } if (any < 0) { acc =3D neg ? LONG_MIN : LONG_MAX; errno =3D ERANGE; } else if (neg) acc =3D -acc; if (endptr !=3D 0) *endptr =3D any ? unconst(s, char *) - 1 : unconst(nptr, char *); return acc; }