diff options
-rw-r--r-- | MANIFEST | 1 | ||||
-rw-r--r-- | hints/uts.sh | 16 | ||||
-rw-r--r-- | uts/strtol_wrap.c | 174 |
3 files changed, 189 insertions, 2 deletions
@@ -1919,6 +1919,7 @@ utils/perlcc.PL Front-end for compiler utils/perldoc.PL A simple tool to find & display perl's documentation utils/pl2pm.PL A pl to pm translator utils/splain.PL Stand-alone version of diagnostics.pm +uts/strtol_wrap.c strtol wrapper for UTS vmesa/Makefile VM/ESA Makefile vmesa/vmesa.c VM/ESA-specific C code for Perl core vmesa/vmesaish.h VM/ESA-specific C header for Perl core diff --git a/hints/uts.sh b/hints/uts.sh index 06a0fdab78..592bc3e84c 100644 --- a/hints/uts.sh +++ b/hints/uts.sh @@ -1,7 +1,8 @@ archname='s390' +archobjs='uts/strtol_wrap.o' cc='cc' cccdlflags='-pic' -ccflags='-Xa -XTSTRINGS=1500000' +ccflags='-Xa -XTSTRINGS=1500000 -DStrtol=strtol_wrap32 -DStrtoul=strtoul_wrap32' d_bincompat3='undef' d_csh='undef' d_lstat='define' @@ -14,6 +15,17 @@ libperl='libperl.so' libpth='/lib /usr/lib /usr/ccs/lib' libs='-lsocket -lnsl -ldl -lm' libswanted='m' -prefix='psf_prefix' +prefix='/usr/local' toke_cflags='optimize=""' useshrplib='define' + +################################# +# Some less routine stuff: +################################# +cc -g -Xa -c -pic -O uts/strtol_wrap.c -o uts/strtol_wrap.o +# Make POSIX a static extension. +cat <<'EOSH' > config.over +static_ext='POSIX B' +dynamic_ext=`echo " $dynamic_ext " | + sed -e 's/ POSIX / /' -e 's/ B / /'` +EOSH diff --git a/uts/strtol_wrap.c b/uts/strtol_wrap.c new file mode 100644 index 0000000000..24bb05542f --- /dev/null +++ b/uts/strtol_wrap.c @@ -0,0 +1,174 @@ +/* A wrapper around strtol() and strtoul() to correct some + * "out of bounds" cases that don't work well on at least UTS. + * If a value is Larger than the max, strto[u]l should return + * the max value, and set errno to ERANGE + * The same if a value is smaller than the min value (only + * relevant for strtol(); not strtoul()), except the minimum + * value is returned (and errno == ERANGE). + */ + +#include <ctype.h> +#include <string.h> +#include <sys/errno.h> +#include <stdlib.h> + +extern int errno; + +#undef I32 +#undef U32 + +#define I32 int +#define U32 unsigned int + +struct base_info { + char *ValidChars; + + char *Ulong_max_str; + char *Long_max_str; + char *Long_min_str; /* Absolute value */ + + int Ulong_max_str_len; + int Long_max_str_len; + int Long_min_str_len; /* Absolute value */ + + U32 Ulong_max; + I32 Long_max; + I32 Long_min; /* NOT Absolute value */ +}; +static struct base_info Base_info[37]; + +static struct base_info Base_info_16 = { + "0123456789abcdefABCDEF", + "4294967295", "2147483648" /* <== ABS VAL */ , "2147483647", + 10, 10, 10, + 4294967295, 2147483647, - 2147483648, +}; + +static struct base_info Base_info_10 = { + "0123456789", + "4294967295", "2147483648" /* <== ABS VAL */ , "2147483647", + 10, 10, 10, + 4294967295, 2147483647, - 2147483648, +}; + + /* Used eventually (if this is fully developed) to hold info + * for processing bases 2-36. So that we can just plug the + * base in as a selector for its info, we sacrifice + * Base_info[0] and Base_info[1] (unless they are used + * at some point for special information). + */ + +/* This may be replaced later by something more universal */ +static void +init_Base_info() +{ + if(Base_info[10].ValidChars) return; + Base_info[10] = Base_info_10; + Base_info[16] = Base_info_16; +} + +unsigned int +strtoul_wrap32(char *s, char **pEnd, int base) +{ + int Len; + int isNegated = 0; + char *sOrig = s; + + init_Base_info(); + + while(*s && isspace(*s)) ++s; + + if(*s == '-') { + ++isNegated; + ++s; + while(*s && isspace(*s)) ++s; + } + if(base == 0) { + if(*s == '0') { + if(s[1] == 'x' || s[1] == 'X') { + s += 2; + base = 16; + } else { + ++s; + base = 8; + } + } else if(isdigit(*s)) { + base = 10; + } + } + if(base != 10) { + return strtoul(sOrig, pEnd, base); + } + + Len = strspn(s, Base_info[base].ValidChars); + + if(Len > Base_info[base].Ulong_max_str_len + || + (Len == Base_info[base].Ulong_max_str_len + && + strncmp(Base_info[base].Ulong_max_str, s, Len) < 0) + ) { + /* In case isNegated is set - what to do?? */ + /* Mightn't we say a negative number is ERANGE for strtoul? */ + errno = ERANGE; + return Base_info[base].Ulong_max; + } + + return strtoul(sOrig, pEnd, base); +} + +int +strtol_wrap32(char *s, char **pEnd, int base) +{ + int Len; + int isNegated = 0; + char *sOrig = s; + + init_Base_info(); + + while(*s && isspace(*s)) ++s; + + if(*s == '-') { + ++isNegated; + ++s; + while(*s && isspace(*s)) ++s; + } + if(base == 0) { + if(*s == '0') { + if(s[1] == 'x' || s[1] == 'X') { + s += 2; + base = 16; + } else { + ++s; + base = 8; + } + } else if(isdigit(*s)) { + base = 10; + } + } + if(base != 10) { + return strtol(sOrig, pEnd, base); + } + + Len = strspn(s, Base_info[base].ValidChars); + + if(Len > Base_info[base].Long_max_str_len + || + (!isNegated && Len == Base_info[base].Long_max_str_len + && + strncmp(Base_info[base].Long_max_str, s, Len) < 0) + || + (isNegated && Len == Base_info[base].Long_min_str_len + && + strncmp(Base_info[base].Long_min_str, s, Len) < 0) + ) { + /* In case isNegated is set - what to do?? */ + /* Mightn't we say a negative number is ERANGE for strtol? */ + errno = ERANGE; + return(isNegated ? Base_info[base].Long_min + : + Base_info[base].Long_min); + } + + return strtol(sOrig, pEnd, base); +} |