[PHP-DEV] CVS update: php3/functions From: cschneid (php-dev <email protected>)
Date: 11/23/98

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 <email protected> |
     +----------------------------------------------------------------------+
! | Authors: Steve Willer <willer <email protected>> |
     +----------------------------------------------------------------------+
   */
! /* $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 <email protected> |
     +----------------------------------------------------------------------+
! | Authors: Chris Schneider <cschneid <email protected>> |
     +----------------------------------------------------------------------+
   */
! /* $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, <email protected>
! * '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, <email protected>
   */
  /* {{{ 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, <email protected>
   */
! /* {{{ 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 <email protected>
For help: php-dev-help <email protected>