Return to pack.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / standard |
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
5: | Copyright (c) 1997-2012 The PHP Group |
6: +----------------------------------------------------------------------+
7: | This source file is subject to version 3.01 of the PHP license, |
8: | that is bundled with this package in the file LICENSE, and is |
9: | available through the world-wide-web at the following url: |
10: | http://www.php.net/license/3_01.txt |
11: | If you did not receive a copy of the PHP license and are unable to |
12: | obtain it through the world-wide-web, please send a note to |
13: | license@php.net so we can mail you a copy immediately. |
14: +----------------------------------------------------------------------+
15: | Author: Chris Schneider <cschneid@relog.ch> |
16: +----------------------------------------------------------------------+
17: */
1.1.1.2 ! misho 18: /* $Id$ */
1.1 misho 19:
20: #include "php.h"
21:
22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <errno.h>
25: #include <sys/types.h>
26: #include <sys/stat.h>
27: #include <fcntl.h>
28: #ifdef PHP_WIN32
29: #define O_RDONLY _O_RDONLY
30: #include "win32/param.h"
31: #elif defined(NETWARE)
32: #ifdef USE_WINSOCK
33: #include <novsock2.h>
34: #else
35: #include <sys/socket.h>
36: #endif
37: #include <sys/param.h>
38: #else
39: #include <sys/param.h>
40: #endif
41: #include "ext/standard/head.h"
42: #include "php_string.h"
43: #include "pack.h"
44: #if HAVE_PWD_H
45: #ifdef PHP_WIN32
46: #include "win32/pwd.h"
47: #else
48: #include <pwd.h>
49: #endif
50: #endif
51: #include "fsock.h"
52: #if HAVE_NETINET_IN_H
53: #include <netinet/in.h>
54: #endif
55:
56: #define INC_OUTPUTPOS(a,b) \
57: if ((a) < 0 || ((INT_MAX - outputpos)/((int)b)) < (a)) { \
58: efree(argv); \
59: efree(formatcodes); \
60: efree(formatargs); \
61: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: integer overflow in format string", code); \
62: RETURN_FALSE; \
63: } \
64: outputpos += (a)*(b);
65:
66: /* Whether machine is little endian */
67: char machine_little_endian;
68:
69: /* Mapping of byte from char (8bit) to long for machine endian */
70: static int byte_map[1];
71:
72: /* Mappings of bytes from int (machine dependant) to int for machine endian */
73: static int int_map[sizeof(int)];
74:
75: /* Mappings of bytes from shorts (16bit) for all endian environments */
76: static int machine_endian_short_map[2];
77: static int big_endian_short_map[2];
78: static int little_endian_short_map[2];
79:
80: /* Mappings of bytes from longs (32bit) for all endian environments */
81: static int machine_endian_long_map[4];
82: static int big_endian_long_map[4];
83: static int little_endian_long_map[4];
84:
85: /* {{{ php_pack
86: */
87: static void php_pack(zval **val, int size, int *map, char *output)
88: {
89: int i;
90: char *v;
91:
92: convert_to_long_ex(val);
93: v = (char *) &Z_LVAL_PP(val);
94:
95: for (i = 0; i < size; i++) {
96: *output++ = v[map[i]];
97: }
98: }
99: /* }}} */
100:
101: /* pack() idea stolen from Perl (implemented formats behave the same as there)
102: * Implemented formats are A, a, h, H, c, C, s, S, i, I, l, L, n, N, f, d, x, X, @.
103: */
104: /* {{{ proto string pack(string format, mixed arg1 [, mixed arg2 [, mixed ...]])
105: Takes one or more arguments and packs them into a binary string according to the format argument */
106: PHP_FUNCTION(pack)
107: {
108: zval ***argv = NULL;
109: int num_args, i;
110: int currentarg;
111: char *format;
112: int formatlen;
113: char *formatcodes;
114: int *formatargs;
115: int formatcount = 0;
116: int outputpos = 0, outputsize = 0;
117: char *output;
118:
119: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &argv, &num_args) == FAILURE) {
120: return;
121: }
122:
123: if (Z_ISREF_PP(argv[0])) {
124: SEPARATE_ZVAL(argv[0]);
125: }
126: convert_to_string_ex(argv[0]);
127:
128: format = Z_STRVAL_PP(argv[0]);
129: formatlen = Z_STRLEN_PP(argv[0]);
130:
131: /* We have a maximum of <formatlen> format codes to deal with */
132: formatcodes = safe_emalloc(formatlen, sizeof(*formatcodes), 0);
133: formatargs = safe_emalloc(formatlen, sizeof(*formatargs), 0);
134: currentarg = 1;
135:
136: /* Preprocess format into formatcodes and formatargs */
137: for (i = 0; i < formatlen; formatcount++) {
138: char code = format[i++];
139: int arg = 1;
140:
141: /* Handle format arguments if any */
142: if (i < formatlen) {
143: char c = format[i];
144:
145: if (c == '*') {
146: arg = -1;
147: i++;
148: }
149: else if (c >= '0' && c <= '9') {
150: arg = atoi(&format[i]);
151:
152: while (format[i] >= '0' && format[i] <= '9' && i < formatlen) {
153: i++;
154: }
155: }
156: }
157:
158: /* Handle special arg '*' for all codes and check argv overflows */
159: switch ((int) code) {
160: /* Never uses any args */
161: case 'x':
162: case 'X':
163: case '@':
164: if (arg < 0) {
165: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: '*' ignored", code);
166: arg = 1;
167: }
168: break;
169:
170: /* Always uses one arg */
171: case 'a':
172: case 'A':
173: case 'h':
174: case 'H':
175: if (currentarg >= num_args) {
176: efree(argv);
177: efree(formatcodes);
178: efree(formatargs);
179: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: not enough arguments", code);
180: RETURN_FALSE;
181: }
182:
183: if (arg < 0) {
184: if (Z_ISREF_PP(argv[currentarg])) {
185: SEPARATE_ZVAL(argv[currentarg]);
186: }
187: convert_to_string_ex(argv[currentarg]);
188: arg = Z_STRLEN_PP(argv[currentarg]);
189: }
190:
191: currentarg++;
192: break;
193:
194: /* Use as many args as specified */
195: case 'c':
196: case 'C':
197: case 's':
198: case 'S':
199: case 'i':
200: case 'I':
201: case 'l':
202: case 'L':
203: case 'n':
204: case 'N':
205: case 'v':
206: case 'V':
207: case 'f':
208: case 'd':
209: if (arg < 0) {
210: arg = num_args - currentarg;
211: }
212:
213: currentarg += arg;
214:
215: if (currentarg > num_args) {
216: efree(argv);
217: efree(formatcodes);
218: efree(formatargs);
219: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: too few arguments", code);
220: RETURN_FALSE;
221: }
222: break;
223:
224: default:
225: efree(argv);
226: efree(formatcodes);
227: efree(formatargs);
228: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: unknown format code", code);
229: RETURN_FALSE;
230: }
231:
232: formatcodes[formatcount] = code;
233: formatargs[formatcount] = arg;
234: }
235:
236: if (currentarg < num_args) {
237: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%d arguments unused", (num_args - currentarg));
238: }
239:
240: /* Calculate output length and upper bound while processing*/
241: for (i = 0; i < formatcount; i++) {
242: int code = (int) formatcodes[i];
243: int arg = formatargs[i];
244:
245: switch ((int) code) {
246: case 'h':
247: case 'H':
248: INC_OUTPUTPOS((arg + (arg % 2)) / 2,1) /* 4 bit per arg */
249: break;
250:
251: case 'a':
252: case 'A':
253: case 'c':
254: case 'C':
255: case 'x':
256: INC_OUTPUTPOS(arg,1) /* 8 bit per arg */
257: break;
258:
259: case 's':
260: case 'S':
261: case 'n':
262: case 'v':
263: INC_OUTPUTPOS(arg,2) /* 16 bit per arg */
264: break;
265:
266: case 'i':
267: case 'I':
268: INC_OUTPUTPOS(arg,sizeof(int))
269: break;
270:
271: case 'l':
272: case 'L':
273: case 'N':
274: case 'V':
275: INC_OUTPUTPOS(arg,4) /* 32 bit per arg */
276: break;
277:
278: case 'f':
279: INC_OUTPUTPOS(arg,sizeof(float))
280: break;
281:
282: case 'd':
283: INC_OUTPUTPOS(arg,sizeof(double))
284: break;
285:
286: case 'X':
287: outputpos -= arg;
288:
289: if (outputpos < 0) {
290: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: outside of string", code);
291: outputpos = 0;
292: }
293: break;
294:
295: case '@':
296: outputpos = arg;
297: break;
298: }
299:
300: if (outputsize < outputpos) {
301: outputsize = outputpos;
302: }
303: }
304:
305: output = emalloc(outputsize + 1);
306: outputpos = 0;
307: currentarg = 1;
308:
309: /* Do actual packing */
310: for (i = 0; i < formatcount; i++) {
311: int code = (int) formatcodes[i];
312: int arg = formatargs[i];
313: zval **val;
314:
315: switch ((int) code) {
316: case 'a':
317: case 'A':
318: memset(&output[outputpos], (code == 'a') ? '\0' : ' ', arg);
319: val = argv[currentarg++];
320: if (Z_ISREF_PP(val)) {
321: SEPARATE_ZVAL(val);
322: }
323: convert_to_string_ex(val);
324: memcpy(&output[outputpos], Z_STRVAL_PP(val),
325: (Z_STRLEN_PP(val) < arg) ? Z_STRLEN_PP(val) : arg);
326: outputpos += arg;
327: break;
328:
329: case 'h':
330: case 'H': {
331: int nibbleshift = (code == 'h') ? 0 : 4;
332: int first = 1;
333: char *v;
334:
335: val = argv[currentarg++];
336: if (Z_ISREF_PP(val)) {
337: SEPARATE_ZVAL(val);
338: }
339: convert_to_string_ex(val);
340: v = Z_STRVAL_PP(val);
341: outputpos--;
342: if(arg > Z_STRLEN_PP(val)) {
343: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: not enough characters in string", code);
344: arg = Z_STRLEN_PP(val);
345: }
346:
347: while (arg-- > 0) {
348: char n = *v++;
349:
350: if (n >= '0' && n <= '9') {
351: n -= '0';
352: } else if (n >= 'A' && n <= 'F') {
353: n -= ('A' - 10);
354: } else if (n >= 'a' && n <= 'f') {
355: n -= ('a' - 10);
356: } else {
357: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: illegal hex digit %c", code, n);
358: n = 0;
359: }
360:
361: if (first--) {
362: output[++outputpos] = 0;
363: } else {
364: first = 1;
365: }
366:
367: output[outputpos] |= (n << nibbleshift);
368: nibbleshift = (nibbleshift + 4) & 7;
369: }
370:
371: outputpos++;
372: break;
373: }
374:
375: case 'c':
376: case 'C':
377: while (arg-- > 0) {
378: php_pack(argv[currentarg++], 1, byte_map, &output[outputpos]);
379: outputpos++;
380: }
381: break;
382:
383: case 's':
384: case 'S':
385: case 'n':
386: case 'v': {
387: int *map = machine_endian_short_map;
388:
389: if (code == 'n') {
390: map = big_endian_short_map;
391: } else if (code == 'v') {
392: map = little_endian_short_map;
393: }
394:
395: while (arg-- > 0) {
396: php_pack(argv[currentarg++], 2, map, &output[outputpos]);
397: outputpos += 2;
398: }
399: break;
400: }
401:
402: case 'i':
403: case 'I':
404: while (arg-- > 0) {
405: php_pack(argv[currentarg++], sizeof(int), int_map, &output[outputpos]);
406: outputpos += sizeof(int);
407: }
408: break;
409:
410: case 'l':
411: case 'L':
412: case 'N':
413: case 'V': {
414: int *map = machine_endian_long_map;
415:
416: if (code == 'N') {
417: map = big_endian_long_map;
418: } else if (code == 'V') {
419: map = little_endian_long_map;
420: }
421:
422: while (arg-- > 0) {
423: php_pack(argv[currentarg++], 4, map, &output[outputpos]);
424: outputpos += 4;
425: }
426: break;
427: }
428:
429: case 'f': {
430: float v;
431:
432: while (arg-- > 0) {
433: val = argv[currentarg++];
434: convert_to_double_ex(val);
435: v = (float) Z_DVAL_PP(val);
436: memcpy(&output[outputpos], &v, sizeof(v));
437: outputpos += sizeof(v);
438: }
439: break;
440: }
441:
442: case 'd': {
443: double v;
444:
445: while (arg-- > 0) {
446: val = argv[currentarg++];
447: convert_to_double_ex(val);
448: v = (double) Z_DVAL_PP(val);
449: memcpy(&output[outputpos], &v, sizeof(v));
450: outputpos += sizeof(v);
451: }
452: break;
453: }
454:
455: case 'x':
456: memset(&output[outputpos], '\0', arg);
457: outputpos += arg;
458: break;
459:
460: case 'X':
461: outputpos -= arg;
462:
463: if (outputpos < 0) {
464: outputpos = 0;
465: }
466: break;
467:
468: case '@':
469: if (arg > outputpos) {
470: memset(&output[outputpos], '\0', arg - outputpos);
471: }
472: outputpos = arg;
473: break;
474: }
475: }
476:
477: efree(argv);
478: efree(formatcodes);
479: efree(formatargs);
480: output[outputpos] = '\0';
481: RETVAL_STRINGL(output, outputpos, 1);
482: efree(output);
483: }
484: /* }}} */
485:
486: /* {{{ php_unpack
487: */
488: static long php_unpack(char *data, int size, int issigned, int *map)
489: {
490: long result;
491: char *cresult = (char *) &result;
492: int i;
493:
494: result = issigned ? -1 : 0;
495:
496: for (i = 0; i < size; i++) {
497: cresult[map[i]] = *data++;
498: }
499:
500: return result;
501: }
502: /* }}} */
503:
504: /* unpack() is based on Perl's unpack(), but is modified a bit from there.
505: * Rather than depending on error-prone ordered lists or syntactically
506: * unpleasant pass-by-reference, we return an object with named paramters
507: * (like *_fetch_object()). Syntax is "f[repeat]name/...", where "f" is the
508: * formatter char (like pack()), "[repeat]" is the optional repeater argument,
509: * and "name" is the name of the variable to use.
510: * Example: "c2chars/nints" will return an object with fields
511: * chars1, chars2, and ints.
512: * Numeric pack types will return numbers, a and A will return strings,
513: * f and d will return doubles.
514: * Implemented formats are A, a, h, H, c, C, s, S, i, I, l, L, n, N, f, d, x, X, @.
515: */
516: /* {{{ proto array unpack(string format, string input)
517: Unpack binary string into named array elements according to format argument */
518: PHP_FUNCTION(unpack)
519: {
520: char *format, *input, *formatarg, *inputarg;
521: int formatlen, formatarg_len, inputarg_len;
522: int inputpos, inputlen, i;
523:
524: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &formatarg, &formatarg_len,
525: &inputarg, &inputarg_len) == FAILURE) {
526: return;
527: }
528:
529: format = formatarg;
530: formatlen = formatarg_len;
531: input = inputarg;
532: inputlen = inputarg_len;
533: inputpos = 0;
534:
535: array_init(return_value);
536:
537: while (formatlen-- > 0) {
538: char type = *(format++);
539: char c;
540: int arg = 1, argb;
541: char *name;
542: int namelen;
543: int size=0;
544:
545: /* Handle format arguments if any */
546: if (formatlen > 0) {
547: c = *format;
548:
549: if (c >= '0' && c <= '9') {
550: arg = atoi(format);
551:
552: while (formatlen > 0 && *format >= '0' && *format <= '9') {
553: format++;
554: formatlen--;
555: }
556: } else if (c == '*') {
557: arg = -1;
558: format++;
559: formatlen--;
560: }
561: }
562:
563: /* Get of new value in array */
564: name = format;
565: argb = arg;
566:
567: while (formatlen > 0 && *format != '/') {
568: formatlen--;
569: format++;
570: }
571:
572: namelen = format - name;
573:
574: if (namelen > 200)
575: namelen = 200;
576:
577: switch ((int) type) {
578: /* Never use any input */
579: case 'X':
580: size = -1;
581: break;
582:
583: case '@':
584: size = 0;
585: break;
586:
587: case 'a':
588: case 'A':
589: size = arg;
590: arg = 1;
591: break;
592:
593: case 'h':
594: case 'H':
595: size = (arg > 0) ? (arg + (arg % 2)) / 2 : arg;
596: arg = 1;
597: break;
598:
599: /* Use 1 byte of input */
600: case 'c':
601: case 'C':
602: case 'x':
603: size = 1;
604: break;
605:
606: /* Use 2 bytes of input */
607: case 's':
608: case 'S':
609: case 'n':
610: case 'v':
611: size = 2;
612: break;
613:
614: /* Use sizeof(int) bytes of input */
615: case 'i':
616: case 'I':
617: size = sizeof(int);
618: break;
619:
620: /* Use 4 bytes of input */
621: case 'l':
622: case 'L':
623: case 'N':
624: case 'V':
625: size = 4;
626: break;
627:
628: /* Use sizeof(float) bytes of input */
629: case 'f':
630: size = sizeof(float);
631: break;
632:
633: /* Use sizeof(double) bytes of input */
634: case 'd':
635: size = sizeof(double);
636: break;
637:
638: default:
639: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid format type %c", type);
640: zval_dtor(return_value);
641: RETURN_FALSE;
642: break;
643: }
644:
645: /* Do actual unpacking */
646: for (i = 0; i != arg; i++ ) {
647: /* Space for name + number, safe as namelen is ensured <= 200 */
648: char n[256];
649:
650: if (arg != 1 || namelen == 0) {
651: /* Need to add element number to name */
652: snprintf(n, sizeof(n), "%.*s%d", namelen, name, i + 1);
653: } else {
654: /* Truncate name to next format code or end of string */
655: snprintf(n, sizeof(n), "%.*s", namelen, name);
656: }
657:
658: if (size != 0 && size != -1 && INT_MAX - size + 1 < inputpos) {
659: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: integer overflow", type);
660: inputpos = 0;
661: }
662:
663: if ((inputpos + size) <= inputlen) {
664: switch ((int) type) {
665: case 'a':
666: case 'A': {
667: char pad = (type == 'a') ? '\0' : ' ';
668: int len = inputlen - inputpos; /* Remaining string */
669:
670: /* If size was given take minimum of len and size */
671: if ((size >= 0) && (len > size)) {
672: len = size;
673: }
674:
675: size = len;
676:
677: /* Remove padding chars from unpacked data */
678: while (--len >= 0) {
679: if (input[inputpos + len] != pad)
680: break;
681: }
682:
683: add_assoc_stringl(return_value, n, &input[inputpos], len + 1, 1);
684: break;
685: }
686:
687: case 'h':
688: case 'H': {
689: int len = (inputlen - inputpos) * 2; /* Remaining */
690: int nibbleshift = (type == 'h') ? 0 : 4;
691: int first = 1;
692: char *buf;
693: int ipos, opos;
694:
695: /* If size was given take minimum of len and size */
696: if (size >= 0 && len > (size * 2)) {
697: len = size * 2;
698: }
699:
700: if (argb > 0) {
701: len -= argb % 2;
702: }
703:
704: buf = emalloc(len + 1);
705:
706: for (ipos = opos = 0; opos < len; opos++) {
707: char cc = (input[inputpos + ipos] >> nibbleshift) & 0xf;
708:
709: if (cc < 10) {
710: cc += '0';
711: } else {
712: cc += 'a' - 10;
713: }
714:
715: buf[opos] = cc;
716: nibbleshift = (nibbleshift + 4) & 7;
717:
718: if (first-- == 0) {
719: ipos++;
720: first = 1;
721: }
722: }
723:
724: buf[len] = '\0';
725: add_assoc_stringl(return_value, n, buf, len, 1);
726: efree(buf);
727: break;
728: }
729:
730: case 'c':
731: case 'C': {
732: int issigned = (type == 'c') ? (input[inputpos] & 0x80) : 0;
733: long v = php_unpack(&input[inputpos], 1, issigned, byte_map);
734: add_assoc_long(return_value, n, v);
735: break;
736: }
737:
738: case 's':
739: case 'S':
740: case 'n':
741: case 'v': {
742: long v;
743: int issigned = 0;
744: int *map = machine_endian_short_map;
745:
746: if (type == 's') {
747: issigned = input[inputpos + (machine_little_endian ? 1 : 0)] & 0x80;
748: } else if (type == 'n') {
749: map = big_endian_short_map;
750: } else if (type == 'v') {
751: map = little_endian_short_map;
752: }
753:
754: v = php_unpack(&input[inputpos], 2, issigned, map);
755: add_assoc_long(return_value, n, v);
756: break;
757: }
758:
759: case 'i':
760: case 'I': {
761: long v = 0;
762: int issigned = 0;
763:
764: if (type == 'i') {
765: issigned = input[inputpos + (machine_little_endian ? (sizeof(int) - 1) : 0)] & 0x80;
766: } else if (sizeof(long) > 4 && (input[inputpos + machine_endian_long_map[3]] & 0x80) == 0x80) {
767: v = ~INT_MAX;
768: }
769:
770: v |= php_unpack(&input[inputpos], sizeof(int), issigned, int_map);
771: add_assoc_long(return_value, n, v);
772: break;
773: }
774:
775: case 'l':
776: case 'L':
777: case 'N':
778: case 'V': {
779: int issigned = 0;
780: int *map = machine_endian_long_map;
781: long v = 0;
782:
783: if (type == 'l' || type == 'L') {
784: issigned = input[inputpos + (machine_little_endian ? 3 : 0)] & 0x80;
785: } else if (type == 'N') {
786: issigned = input[inputpos] & 0x80;
787: map = big_endian_long_map;
788: } else if (type == 'V') {
789: issigned = input[inputpos + 3] & 0x80;
790: map = little_endian_long_map;
791: }
792:
793: if (sizeof(long) > 4 && issigned) {
794: v = ~INT_MAX;
795: }
796:
797: v |= php_unpack(&input[inputpos], 4, issigned, map);
798: if (sizeof(long) > 4) {
799: if (type == 'l') {
800: v = (signed int) v;
801: } else {
802: v = (unsigned int) v;
803: }
804: }
805: add_assoc_long(return_value, n, v);
806: break;
807: }
808:
809: case 'f': {
810: float v;
811:
812: memcpy(&v, &input[inputpos], sizeof(float));
813: add_assoc_double(return_value, n, (double)v);
814: break;
815: }
816:
817: case 'd': {
818: double v;
819:
820: memcpy(&v, &input[inputpos], sizeof(double));
821: add_assoc_double(return_value, n, v);
822: break;
823: }
824:
825: case 'x':
826: /* Do nothing with input, just skip it */
827: break;
828:
829: case 'X':
830: if (inputpos < size) {
831: inputpos = -size;
832: i = arg - 1; /* Break out of for loop */
833:
834: if (arg >= 0) {
835: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: outside of string", type);
836: }
837: }
838: break;
839:
840: case '@':
841: if (arg <= inputlen) {
842: inputpos = arg;
843: } else {
844: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: outside of string", type);
845: }
846:
847: i = arg - 1; /* Done, break out of for loop */
848: break;
849: }
850:
851: inputpos += size;
852: if (inputpos < 0) {
853: if (size != -1) { /* only print warning if not working with * */
854: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: outside of string", type);
855: }
856: inputpos = 0;
857: }
858: } else if (arg < 0) {
859: /* Reached end of input for '*' repeater */
860: break;
861: } else {
862: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: not enough input, need %d, have %d", type, size, inputlen - inputpos);
863: zval_dtor(return_value);
864: RETURN_FALSE;
865: }
866: }
867:
868: formatlen--; /* Skip '/' separator, does no harm if inputlen == 0 */
869: format++;
870: }
871: }
872: /* }}} */
873:
874: /* {{{ PHP_MINIT_FUNCTION
875: */
876: PHP_MINIT_FUNCTION(pack)
877: {
878: int machine_endian_check = 1;
879: int i;
880:
881: machine_little_endian = ((char *)&machine_endian_check)[0];
882:
883: if (machine_little_endian) {
884: /* Where to get lo to hi bytes from */
885: byte_map[0] = 0;
886:
887: for (i = 0; i < (int)sizeof(int); i++) {
888: int_map[i] = i;
889: }
890:
891: machine_endian_short_map[0] = 0;
892: machine_endian_short_map[1] = 1;
893: big_endian_short_map[0] = 1;
894: big_endian_short_map[1] = 0;
895: little_endian_short_map[0] = 0;
896: little_endian_short_map[1] = 1;
897:
898: machine_endian_long_map[0] = 0;
899: machine_endian_long_map[1] = 1;
900: machine_endian_long_map[2] = 2;
901: machine_endian_long_map[3] = 3;
902: big_endian_long_map[0] = 3;
903: big_endian_long_map[1] = 2;
904: big_endian_long_map[2] = 1;
905: big_endian_long_map[3] = 0;
906: little_endian_long_map[0] = 0;
907: little_endian_long_map[1] = 1;
908: little_endian_long_map[2] = 2;
909: little_endian_long_map[3] = 3;
910: }
911: else {
912: zval val;
913: int size = sizeof(Z_LVAL(val));
914: Z_LVAL(val)=0; /*silence a warning*/
915:
916: /* Where to get hi to lo bytes from */
917: byte_map[0] = size - 1;
918:
919: for (i = 0; i < (int)sizeof(int); i++) {
920: int_map[i] = size - (sizeof(int) - i);
921: }
922:
923: machine_endian_short_map[0] = size - 2;
924: machine_endian_short_map[1] = size - 1;
925: big_endian_short_map[0] = size - 2;
926: big_endian_short_map[1] = size - 1;
927: little_endian_short_map[0] = size - 1;
928: little_endian_short_map[1] = size - 2;
929:
930: machine_endian_long_map[0] = size - 4;
931: machine_endian_long_map[1] = size - 3;
932: machine_endian_long_map[2] = size - 2;
933: machine_endian_long_map[3] = size - 1;
934: big_endian_long_map[0] = size - 4;
935: big_endian_long_map[1] = size - 3;
936: big_endian_long_map[2] = size - 2;
937: big_endian_long_map[3] = size - 1;
938: little_endian_long_map[0] = size - 1;
939: little_endian_long_map[1] = size - 2;
940: little_endian_long_map[2] = size - 3;
941: little_endian_long_map[3] = size - 4;
942: }
943:
944: return SUCCESS;
945: }
946: /* }}} */
947:
948: /*
949: * Local variables:
950: * tab-width: 4
951: * c-basic-offset: 4
952: * End:
953: * vim600: noet sw=4 ts=4 fdm=marker
954: * vim<600: noet sw=4 ts=4
955: */