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