CVS update: php3/functions

From: Date: Mon, 23 Nov 1998 18:13:09 +0000
Subject: CVS update: php3/functions
Groups: php.dev 
Request: Send a blank email to php-dev+get-2561@lists.php.net to get a copy of this message
Date: Monday November 23, 1998 @ 13:13 Author: cschneid Update of /repository/php3/functions In directory asf:/u2/tmp/cvs-serv3598/functions Modified Files: pack.c Log Message: Functions pack() and unpack() rewritten to be binary and buffer overrun safe and behave like the Perl functions for all implemented format codes. Index: php3/functions/pack.c diff -c php3/functions/pack.c:1.18 php3/functions/pack.c:1.19 *** php3/functions/pack.c:1.18 Wed Nov 18 16:23:10 1998 --- php3/functions/pack.c Mon Nov 23 13:13:08 1998 *************** *** 23,32 **** | If you did not, or have any questions about PHP licensing, please | | contact core@php.net. | +----------------------------------------------------------------------+ ! | Authors: Steve Willer <willer@interlog.com> | +----------------------------------------------------------------------+ */ ! /* $Id: pack.c,v 1.18 1998/11/18 21:23:10 ssb Exp $ */ #ifdef THREAD_SAFE #include "tls.h" #endif --- 23,32 ---- | If you did not, or have any questions about PHP licensing, please | | contact core@php.net. | +----------------------------------------------------------------------+ ! | Authors: Chris Schneider <cschneid@relog.ch> | +----------------------------------------------------------------------+ */ ! /* $Id: pack.c,v 1.19 1998/11/23 18:13:08 cschneid Exp $ */ #ifdef THREAD_SAFE #include "tls.h" #endif *************** *** 75,279 **** "PHP_pack", pack_functions, php3_minit_pack, NULL, NULL, NULL, NULL, STANDARD_MODULE_PROPERTIES }; ! /* pack() idea stolen from Perl. Implemented formats are A,a,c,C,s,S,i,I,l,L,n,N,f,d,x,X,@. ! * 'h' is also implemented, but I'm not sure if it works the same way as Perl */ /* {{{ proto string pack(string format, mixed arg1, mixed arg2, ...) Takes 1 or more arguments and packs them into a binary string according to the format argument */ ! void php3_pack(INTERNAL_FUNCTION_PARAMETERS) { ! pval **args; ! int argc, currarg = 1, size = 240; ! const char *format; ! char thisformat = '\0'; ! char *out, *outstart; ! int repeat = 0; ! signed char c; ! unsigned char C; ! signed short s; ! unsigned short S; ! signed int i; ! unsigned int I; ! signed long l; ! unsigned long L; ! float f; ! double d; argc = ARG_COUNT(ht); if (argc < 1) { WRONG_PARAM_COUNT; } - args = emalloc(argc * sizeof(pval *)); ! if (getParametersArray(ht, argc, args) == FAILURE) { ! efree(args); WRONG_PARAM_COUNT; } ! convert_to_string(args[0]); ! out = outstart = emalloc(size); ! /* I got tired of seeing warnings under msvc so ! is some places where this macro was used, I replaced ! it with actual code */ ! #define CASEFOR(vartype,var) \ ! case vartype:\ ! convert_to_long(args[currarg]);\ ! var = args[currarg]->value.lval;\ ! memcpy(out, &var, sizeof(var));\ ! out += sizeof(var);\ ! currarg++;\ ! break; ! ! format = args[0]->value.str.val; ! while (*format || repeat) { ! char repeatbuf[32]; ! int inpos; ! ! /* make sure we didn't go past the end */ ! if (currarg >= argc && *format != 'x' && *format != 'X' && *format != '@') { ! php3_error(E_WARNING,"pack: too few arguments"); ! break; ! } ! if (repeat == 0) { ! thisformat = *(format++); ! /* grab any repeater args */ ! if (*format == '*') { ! repeat = 32000; ! } ! else { ! for (repeat = 0; *format && *format >= '0' && *format <= '9'; format++, repeat++) ! repeatbuf[repeat] = *format; ! repeatbuf[repeat] = '\0'; ! repeat = atoi(repeatbuf); ! if (repeat == 0) ! repeat = 1; ! } ! } ! ! /* handle the format char */ ! switch (thisformat) { ! case 'A': ! case 'a': ! convert_to_string(args[currarg]); ! for (inpos = 0; inpos < repeat; inpos++) ! if (inpos >= args[currarg]->value.str.len) ! *(out++) = (thisformat == 'A') ? ' ' : '\0'; ! else ! *(out++) = args[currarg]->value.str.val[inpos]; ! repeat = 0; ! currarg++; ! break; ! case 'h': ! convert_to_string(args[currarg]); ! for (inpos = 0; inpos < args[currarg]->value.str.len; inpos++) { ! sprintf(out, "%02x", (int)args[currarg]->value.str.val[inpos]); ! out += 2; ! } ! currarg++; ! break; ! case 'c': ! convert_to_long(args[currarg]); ! c = (signed char)args[currarg]->value.lval; ! memcpy(out, &c, sizeof(c)); ! out += sizeof(c); ! currarg++; ! break; ! case 'C': ! convert_to_long(args[currarg]); ! C = (unsigned char)args[currarg]->value.lval; ! memcpy(out, &C, sizeof(C)); ! out += sizeof(C); ! currarg++; ! break; ! case 's': ! convert_to_long(args[currarg]); ! s = (signed short)args[currarg]->value.lval; ! memcpy(out, &s, sizeof(s)); ! out += sizeof(s); ! currarg++; ! break; ! case 'S': ! convert_to_long(args[currarg]); ! S = (unsigned short)args[currarg]->value.lval; ! memcpy(out, &S, sizeof(S)); ! out += sizeof(S); ! currarg++; ! break; ! CASEFOR('i', i); ! CASEFOR('I', I); ! CASEFOR('l', l); ! CASEFOR('L', L); ! case 'n': ! convert_to_long(args[currarg]); ! S = htons((unsigned short)args[currarg]->value.lval); ! memcpy(out, &S, sizeof(S)); ! out += sizeof(S); ! currarg++; ! break; ! case 'N': ! convert_to_long(args[currarg]); ! L = htonl(args[currarg]->value.lval); ! memcpy(out, &L, sizeof(L)); ! out += sizeof(L); ! currarg++; ! break; ! case 'f': ! convert_to_long(args[currarg]); ! f = (float)args[currarg]->value.lval; ! memcpy(out, &f, sizeof(f)); ! out += sizeof(f); ! currarg++; ! break; ! CASEFOR('d', d); ! case 'x': ! *(out++) = '\0'; ! break; ! case 'X': ! out--; ! break; ! case '@': ! /* repeat == the length to which we should pad */ ! while (out - outstart < repeat) ! *(out++) = '\0'; ! repeat = 0; ! break; ! default: ! php3_error(E_WARNING,"pack: unknown format type '%c'", *format); ! break; ! } ! if (repeat) ! repeat--; ! } ! #undef CASEFOR ! ! efree(args); ! RETVAL_STRINGL(outstart, out - outstart, 1); ! efree(outstart); ! return; } /* }}} */ ! /* unpack() is based on Perl's unpack(), but is modified quite a bit from there. ! * Rather than depending on error-prone ordered lists or syntactically unpleasant ! * pass-by-reference, we return an object with named paramters ! * (like *_fetch_object()). Syntax is "f[rpt]name/...", where "f" is the ! * formatter char (like pack()), "[rpt]" is the optional repeater argument, * and "name" is the name of the variable to use. ! * Example: "c2chars/nints" will return an object with fields chars1, chars2, and ints. * Numeric pack types will return numbers, a and A will return strings, ! * f and d will return */ ! void php3_unpack(INTERNAL_FUNCTION_PARAMETERS) { ! return; } int php3_minit_pack(INIT_FUNC_ARGS) { TLS_VARS; ! return SUCCESS; } --- 75,884 ---- "PHP_pack", pack_functions, php3_minit_pack, NULL, NULL, NULL, NULL, STANDARD_MODULE_PROPERTIES }; ! /* Whether machine is little endian */ ! char machine_little_endian; ! ! /* Mapping of byte from char (8bit) to long for machine endian */ ! static int byte_map[1]; ! ! /* Mappings of bytes from int (machine dependant) to int for machine endian */ ! static int int_map[sizeof(int)]; ! ! /* Mappings of bytes from shorts (16bit) for all endian environments */ ! static int machine_endian_short_map[2]; ! static int big_endian_short_map[2]; ! static int little_endian_short_map[2]; ! ! /* Mappings of bytes from longs (32bit) for all endian environments */ ! static int machine_endian_long_map[4]; ! static int big_endian_long_map[4]; ! static int little_endian_long_map[4]; ! ! ! static void _php3_pack(pval *val, int size, int *map, char *output) ! { ! int i; ! char *v; ! ! convert_to_long(val); ! v = (char *)&val->value.lval; ! ! for (i = 0; i < size; i++) { ! *(output++) = v[map[i]]; ! } ! } ! ! ! /* pack() idea stolen from Perl (implemented formats behave the same as there) ! * Implemented formats are A,a,h,H,c,C,s,S,i,I,l,L,n,N,f,d,x,X,@. */ /* {{{ proto string pack(string format, mixed arg1, mixed arg2, ...) Takes 1 or more arguments and packs them into a binary string according to the format argument */ ! PHP_FUNCTION(pack) ! { ! pval **argv; ! int argc, i; ! int currentarg; ! char *format; ! int formatlen; ! char *formatcodes; ! int *formatargs; ! int formatcount = 0; ! int outputpos = 0, outputsize = 0; ! char *output; ! TLS_VARS; argc = ARG_COUNT(ht); if (argc < 1) { WRONG_PARAM_COUNT; } ! argv = emalloc(argc * sizeof(pval *)); ! ! if (getParametersArray(ht, argc, argv) == FAILURE) { ! efree(argv); WRONG_PARAM_COUNT; + } + + convert_to_string(argv[0]); + format = argv[0]->value.str.val; + formatlen = argv[0]->value.str.len; + + /* We have a maximum of <formatlen> format codes to deal with */ + formatcodes = emalloc(formatlen * sizeof(*formatcodes)); + formatargs = emalloc(formatlen * sizeof(*formatargs)); + currentarg = 1; + + /* Preprocess format into formatcodes and formatargs */ + for (i = 0; i < formatlen; formatcount++) { + char code = format[i++]; + int arg = 1; + + /* Handle format arguments if any */ + if (i < formatlen) { + char c = format[i]; + + if (c == '*') { + arg = -1; + i++; + } + else if ((c >= '0') && (c <= '9')) { + arg = atoi(&format[i]); + + while (format[i] >= '0' && format[i] <= '9' && i < formatlen) { + i++; + } + } + } + + /* Handle special arg '*' for all codes and check argv overflows */ + switch ((int)code) { + /* Never uses any args */ + case 'x': case 'X': case '@': { + if (arg < 0) { + php3_error(E_WARNING, "pack type %c: '*' ignored", code); + arg = 1; + } + break; + } + + /* Always uses one arg */ + case 'a': case 'A': case 'h': case 'H': { + if (currentarg >= argc) { + efree(argv); + efree(formatcodes); + efree(formatargs); + php3_error(E_ERROR, "pack type %c: not enough arguments", code); + RETURN_FALSE; + } + + if (arg < 0) { + arg = argv[currentarg]->value.str.len; + } + + currentarg++; + break; + } + + /* Use as many args as specified */ + case 'c': case 'C': case 's': case 'S': case 'i': case 'I': + case 'l': case 'L': case 'n': case 'N': case 'v': case 'V': + case 'f': case 'd': { + if (arg < 0) { + arg = argc - currentarg; + } + + currentarg += arg; + + if (currentarg > argc) { + efree(argv); + efree(formatcodes); + efree(formatargs); + php3_error(E_ERROR, "pack type %c: too few arguments", code); + RETURN_FALSE; + } + break; + } + + default: { + php3_error(E_ERROR, "pack type %c: unknown format code", code); + RETURN_FALSE; + } + } + + formatcodes[formatcount] = code; + formatargs[formatcount] = arg; + } + + if (currentarg < argc) { + php3_error(E_WARNING, "pack %d arguments unused", (argc - currentarg)); } ! ! /* Calculate output length and upper bound while processing*/ ! for (i = 0; i < formatcount; i++) { ! int code = (int)formatcodes[i]; ! int arg = formatargs[i]; ! ! switch ((int)code) { ! case 'h': case 'H': { ! outputpos += (arg + 1) / 2; /* 4 bit per arg */ ! break; ! } ! ! case 'a': case 'A': ! case 'c': case 'C': ! case 'x': { ! outputpos += arg; /* 8 bit per arg */ ! break; ! } ! ! case 's': case 'S': case 'n': case 'v': { ! outputpos += arg * 2; /* 16 bit per arg */ ! break; ! } ! ! case 'i': case 'I': { ! outputpos += arg * sizeof(int); ! break; ! } ! ! case 'l': case 'L': case 'N': case 'V': { ! outputpos += arg * 4; /* 32 bit per arg */ ! break; ! } ! ! case 'f': { ! outputpos += arg * sizeof(float); ! break; ! } ! ! case 'd': { ! outputpos += arg * sizeof(double); ! break; ! } ! ! case 'X': { ! outputpos -= arg; ! ! if (outputpos < 0) { ! php3_error(E_WARNING, "pack type %c: outside of string", code); ! outputpos = 0; ! } ! break; ! } ! ! case '@': { ! outputpos = arg; ! break; ! } ! } ! ! if (outputsize < outputpos) { ! outputsize = outputpos; ! } ! } ! ! output = emalloc(outputsize + 1); ! outputpos = 0; ! currentarg = 1; ! ! /* Do actual packing */ ! for (i = 0; i < formatcount; i++) { ! int code = (int)formatcodes[i]; ! int arg = formatargs[i]; ! pval *val; ! ! switch ((int)code) { ! case 'a': case 'A': { ! memset(&output[outputpos], (code == 'a') ? '\0' : ' ', arg); ! val = argv[currentarg++]; ! convert_to_string(val); ! memcpy(&output[outputpos], val->value.str.val, ! (val->value.str.len < arg) ? val->value.str.len : arg); ! outputpos += arg; ! break; ! } ! ! case 'h': case 'H': { ! int nibbleshift = (code == 'h') ? 0 : 4; ! int first = 1; ! char *v; ! ! val = argv[currentarg++]; ! convert_to_string(val); ! v = val->value.str.val; ! outputpos--; ! ! while (arg-- > 0) { ! char n = *(v++); ! ! if ((n >= '0') && (n <= '9')) { ! n -= '0'; ! } else if ((n >= 'A') && (n <= 'F')) { ! n -= ('A' - 10); ! } else if ((n >= 'a') && (n <= 'f')) { ! n -= ('a' - 10); ! } else { ! php3_error(E_WARNING, "pack type %c: illegal hex digit %c", code, n); ! n = 0; ! } ! ! if (first--) { ! output[++outputpos] = 0; ! } else { ! first = 1; ! } ! ! output[outputpos] |= (n << nibbleshift); ! nibbleshift = (nibbleshift + 4) & 7; ! } ! ! outputpos++; ! break; ! } ! ! case 'c': case 'C': { ! while (arg-- > 0) { ! _php3_pack(argv[currentarg++], 1, byte_map, &output[outputpos]); ! outputpos++; ! } ! break; ! } ! ! case 's': case 'S': case 'n': case 'v': { ! int *map = machine_endian_short_map; ! ! if (code == 'n') { ! map = big_endian_short_map; ! } else if (code == 'v') { ! map = little_endian_short_map; ! } ! ! while (arg-- > 0) { ! _php3_pack(argv[currentarg++], 2, map, &output[outputpos]); ! outputpos += 2; ! } ! break; ! } ! ! case 'i': case 'I': { ! while (arg-- > 0) { ! _php3_pack(argv[currentarg++], sizeof(int), int_map, &output[outputpos]); ! outputpos += sizeof(int); ! } ! break; ! } ! case 'l': case 'L': case 'N': case 'V': { ! int *map = machine_endian_long_map; ! if (code == 'N') { ! map = big_endian_long_map; ! } else if (code == 'V') { ! map = little_endian_long_map; ! } ! ! while (arg-- > 0) { ! _php3_pack(argv[currentarg++], 4, map, &output[outputpos]); ! outputpos += 4; ! } ! break; ! } ! ! case 'f': { ! float v; ! ! while (arg-- > 0) { ! val = argv[currentarg++]; ! convert_to_double(val); ! v = (float)val->value.dval; ! memcpy(&output[outputpos], &v, sizeof(v)); ! outputpos += sizeof(v); ! } ! break; ! } ! ! case 'd': { ! double v; ! ! while (arg-- > 0) { ! val = argv[currentarg++]; ! convert_to_double(val); ! v = (double)val->value.dval; ! memcpy(&output[outputpos], &v, sizeof(v)); ! outputpos += sizeof(v); ! } ! break; ! } ! ! case 'x': { ! memset(&output[outputpos], '\0', arg); ! outputpos += arg; ! break; ! } ! ! case 'X': { ! outputpos -= arg; ! ! if (outputpos < 0) { ! outputpos = 0; ! } ! break; ! } ! ! case '@': { ! if (arg > outputpos) { ! memset(&output[outputpos], '\0', arg - outputpos); ! } ! outputpos = arg; ! break; ! } ! } ! } ! ! efree(argv); ! efree(formatcodes); ! efree(formatargs); ! output[outputpos] = '\0'; ! RETVAL_STRINGL(output, outputpos, 1); ! efree(output); } /* }}} */ + + static long _php3_unpack(char *data, int size, int issigned, int *map) + { + long result; + char *cresult = (char *)&result; + int i; + + result = issigned ? -1 : 0; ! for (i = 0; i < size; i++) { ! cresult[map[i]] = *(data++); ! } ! ! return result; ! } ! ! ! /* unpack() is based on Perl's unpack(), but is modified a bit from there. ! * Rather than depending on error-prone ordered lists or syntactically ! * unpleasant pass-by-reference, we return an object with named paramters ! * (like *_fetch_object()). Syntax is "f[repeat]name/...", where "f" is the ! * formatter char (like pack()), "[repeatt]" is the optional repeater argument, * and "name" is the name of the variable to use. ! * Example: "c2chars/nints" will return an object with fields ! * chars1, chars2, and ints. * Numeric pack types will return numbers, a and A will return strings, ! * f and d will return doubles. ! * Implemented formats are A,a,h,H,c,C,s,S,i,I,l,L,n,N,f,d,x,X,@. */ ! /* {{{ proto array unpack(string format, string input) ! Unpack binary string into named array elements according to format argument */ ! PHP_FUNCTION(unpack) ! { ! pval *formatarg; ! pval *inputarg; ! char *format; ! char *input; ! int formatlen; ! int inputpos, inputlen; ! int i; ! TLS_VARS; ! ! if ((ARG_COUNT(ht) != 2) || getParameters(ht, 2, &formatarg, &inputarg) == FAILURE) { ! WRONG_PARAM_COUNT; ! } ! ! convert_to_string(formatarg); ! convert_to_string(inputarg); ! ! format = formatarg->value.str.val; ! formatlen = formatarg->value.str.len; ! input = inputarg->value.str.val; ! inputlen = inputarg->value.str.len; ! inputpos = 0; ! ! if (array_init(return_value) == FAILURE) ! return; ! ! while (formatlen-- > 0) { ! char type = *(format++); ! char c; ! int arg = 1; ! char *name; ! int namelen; ! int size; ! ! /* Handle format arguments if any */ ! if (formatlen > 0) { ! c = *format; ! ! if ((c >= '0') && (c <= '9')) { ! arg = atoi(format); ! ! while ((formatlen > 0) && (*format >= '0') && (*format <= '9')) { ! format++; ! formatlen--; ! } ! } else if (c == '*') { ! arg = -1; ! format++; ! formatlen--; ! } ! } ! ! /* Get of new value in array */ ! name = format; ! ! while ((formatlen > 0) && (*format != '/')) { ! formatlen--; ! format++; ! } ! ! namelen = format - name; ! ! if (namelen > 200) ! namelen = 200; ! ! switch ((int)type) { ! /* Never use any input */ ! case 'X': { ! size = -1; ! break; ! } ! ! case '@': { ! size = 0; ! break; ! } ! ! case 'a': case 'A': case 'h': case 'H': { ! size = arg; ! arg = 1; ! break; ! } ! ! /* Use 1 byte of input */ ! case 'c': case 'C': case 'x': { ! size = 1; ! break; ! } ! ! /* Use 2 bytes of input */ ! case 's': case 'S': case 'n': case 'v': { ! size = 2; ! break; ! } ! ! /* Use sizeof(int) bytes of input */ ! case 'i': case 'I': { ! size = sizeof(int); ! break; ! } ! ! /* Use 4 bytes of input */ ! case 'l': case 'L': case 'N': case 'V': { ! size = 4; ! break; ! } ! ! /* Use sizeof(float) bytes of input */ ! case 'f': { ! size = sizeof(float); ! break; ! } ! ! /* Use sizeof(double) bytes of input */ ! case 'd': { ! size = sizeof(double); ! break; ! } ! } ! ! /* Do actual unpacking */ ! for (i = 0; (i != arg); i++ ) { ! /* Space for name + number, safe as namelen is ensured <= 200 */ ! char n[256]; ! ! if (arg != 1) { ! /* Need to add element number to name */ ! sprintf(n, "%.*s%d", namelen, name, i + 1); ! } else { ! /* Truncate name to next format code or end of string */ ! sprintf(n, "%.*s", namelen, name); ! } ! ! if ((inputpos + size) <= inputlen) { ! switch ((int)type) { ! case 'a': case 'A': { ! char pad = (type == 'a') ? '\0' : ' '; ! int len = inputlen - inputpos; /* Remaining string */ ! ! /* If size was given take minimum of len and size */ ! if ((size >= 0) && (len > size)) { ! len = size; ! } ! ! size = len; ! ! /* Remove padding chars from unpacked data */ ! while (--len >= 0) { ! if (input[inputpos + len] != pad) ! break; ! } ! ! add_assoc_stringl(return_value, n, &input[inputpos], len + 1, 1); ! break; ! } ! ! case 'h': case 'H': { ! int len = (inputlen - inputpos) * 2; /* Remaining */ ! int nibbleshift = (type == 'h') ? 0 : 4; ! int first = 1; ! char *buf; ! int ipos, opos; ! ! /* If size was given take minimum of len and size */ ! if ((size >= 0) && (len > size)) { ! len = size; ! } ! ! size = (len + 1) / 2; ! buf = emalloc(len + 1); ! ! for (ipos = opos = 0; opos < len; opos++) { ! char c = (input[inputpos + ipos] >> nibbleshift) & 0xf; ! ! if (c < 10) { ! c += '0'; ! } else { ! c += 'a' - 10; ! } ! ! buf[opos] = c; ! nibbleshift = (nibbleshift + 4) & 7; ! ! if (first-- == 0) { ! ipos++; ! first = 1; ! } ! } ! ! buf[len] = '\0'; ! add_assoc_stringl(return_value, n, buf, len, 1); ! efree(buf); ! break; ! } ! ! case 'c': case 'C': { ! int issigned = (type == 'c') ? (input[inputpos] & 0x80) : 0; ! long v = _php3_unpack(&input[inputpos], 1, issigned, byte_map); ! add_assoc_long(return_value, n, v); ! break; ! } ! ! case 's': case 'S': case 'n': case 'v': { ! long v; ! int issigned = 0; ! int *map = machine_endian_short_map; ! ! if (type == 's') { ! issigned = input[inputpos + (machine_little_endian ? 1 : 0)] & 0x80; ! } else if (type == 'n') { ! map = big_endian_short_map; ! } else if (type == 'v') { ! map = little_endian_short_map; ! } ! ! v = _php3_unpack(&input[inputpos], 2, issigned, map); ! add_assoc_long(return_value, n, v); ! break; ! } ! ! case 'i': case 'I': { ! long v; ! int issigned = 0; ! ! if (type == 'i') { ! issigned = input[inputpos + (machine_little_endian ? (sizeof(int) - 1) : 0)] & 0x80; ! } ! ! v = _php3_unpack(&input[inputpos], sizeof(int), issigned, int_map); ! add_assoc_long(return_value, n, v); ! break; ! } ! ! case 'l': case 'L': case 'N': case 'V': { ! int issigned = 0; ! int *map = machine_endian_long_map; ! long v; ! ! if (type == 'l') { ! issigned = input[inputpos + (machine_little_endian ? 3 : 0)] & 0x80; ! } else if (type == 'N') { ! map = big_endian_long_map; ! } else if (type == 'V') { ! map = little_endian_long_map; ! } ! ! v = _php3_unpack(&input[inputpos], 4, issigned, map); ! add_assoc_long(return_value, n, v); ! break; ! } ! ! case 'f': { ! float v; ! ! memcpy(&v, &input[inputpos], sizeof(float)); ! add_assoc_double(return_value, n, (double)v); ! break; ! } ! ! case 'd': { ! double v; ! ! memcpy(&v, &input[inputpos], sizeof(float)); ! add_assoc_double(return_value, n, v); ! break; ! } ! ! case 'x': { ! /* Do nothing with input, just skip it */ ! break; ! } ! ! case 'X': { ! if (inputpos < size) { ! inputpos = -size; ! i = arg - 1; /* Break out of for loop */ ! ! if (arg >= 0) { ! php3_error(E_WARNING, "pack type %c: outside of string", type); ! } ! } ! break; ! } ! ! case '@': { ! if (arg <= inputlen) { ! inputpos = arg; ! } else { ! php3_error(E_WARNING, "pack type %c: outside of string", type); ! } ! ! i = arg - 1; /* Done, break out of for loop */ ! break; ! } ! } ! ! inputpos += size; ! } else if (arg < 0) { ! /* Reached end of input for '*' repeater */ ! break; ! } else { ! php3_error(E_ERROR, "pack type %c: not enough input, need %d, have %d", type, size, inputlen - inputpos); ! RETURN_FALSE; ! } ! } ! ! formatlen--; /* Skip '/' separator, does no harm if inputlen == 0 */ ! format++; ! } } + /* }}} */ int php3_minit_pack(INIT_FUNC_ARGS) { + int machine_endian_check = 1; + int i; TLS_VARS; ! ! machine_little_endian = ((char *)&machine_endian_check)[0]; ! ! if (machine_little_endian) { ! /* Where to get lo to hi bytes from */ ! byte_map[0] = 0; ! ! for (i = 0; i < sizeof(int); i++) { ! int_map[i] = i; ! } ! ! machine_endian_short_map[0] = 0; ! machine_endian_short_map[1] = 1; ! big_endian_short_map[0] = 1; ! big_endian_short_map[1] = 0; ! little_endian_short_map[0] = 0; ! little_endian_short_map[1] = 1; ! ! machine_endian_long_map[0] = 0; ! machine_endian_long_map[1] = 1; ! machine_endian_long_map[2] = 2; ! machine_endian_long_map[3] = 3; ! big_endian_long_map[0] = 3; ! big_endian_long_map[1] = 2; ! big_endian_long_map[2] = 1; ! big_endian_long_map[3] = 0; ! little_endian_long_map[0] = 0; ! little_endian_long_map[1] = 1; ! little_endian_long_map[2] = 2; ! little_endian_long_map[3] = 3; ! } ! else { ! pval val; ! int size = sizeof(val.value.lval); ! ! /* Where to get hi to lo bytes from */ ! byte_map[0] = size - 1; ! ! for (i = 0; i < sizeof(int); i++) { ! int_map[i] = size - (sizeof(int) - i); ! } ! ! machine_endian_short_map[0] = size - 2; ! machine_endian_short_map[1] = size - 1; ! big_endian_short_map[0] = size - 2; ! big_endian_short_map[1] = size - 1; ! little_endian_short_map[0] = size - 1; ! little_endian_short_map[1] = size - 2; ! ! machine_endian_long_map[0] = size - 4; ! machine_endian_long_map[1] = size - 3; ! machine_endian_long_map[2] = size - 2; ! machine_endian_long_map[3] = size - 1; ! big_endian_long_map[0] = size - 4; ! big_endian_long_map[1] = size - 3; ! big_endian_long_map[2] = size - 2; ! big_endian_long_map[3] = size - 1; ! little_endian_long_map[0] = size - 1; ! little_endian_long_map[1] = size - 2; ! little_endian_long_map[2] = size - 3; ! little_endian_long_map[3] = size - 4; ! } ! return SUCCESS; } -- PHP Development Mailing List http://www.php.net/ To unsubscribe send an empty message to php-dev-unsubscribe@lists.php.net For help: php-dev-help@lists.php.net

« previous php.dev (#2561) next »