Index: structmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/structmodule.c,v retrieving revision 2.61 diff -c -r2.61 structmodule.c *** structmodule.c 19 Nov 2003 22:52:23 -0000 2.61 --- structmodule.c 23 Nov 2003 22:10:19 -0000 *************** *** 944,960 **** } ! /* calculate the size of a format string */ static int ! calcsize(const char *fmt, const formatdef *f) { const formatdef *e; const char *s; char c; ! int size, num, itemsize, x; ! s = fmt; size = 0; while ((c = *s++) != '\0') { if (isspace((int)c)) --- 944,960 ---- } ! /* groups are delimited with parentheses in a format string */ static int ! group_calcsize(const char **pfmt, const formatdef *f, int lvl) { const formatdef *e; const char *s; char c; ! int size, num, itemsize, x; ! s = *pfmt; size = 0; while ((c = *s++) != '\0') { if (isspace((int)c)) *************** *** 977,999 **** else num = 1; ! e = getentry(c, f); ! if (e == NULL) ! return -1; ! itemsize = e->size; ! size = align(size, c, e); ! x = num * itemsize; ! size += x; ! if (x/itemsize != num || size < 0) { ! PyErr_SetString(StructError, ! "total struct size too long"); ! return -1; } } return size; } PyDoc_STRVAR(calcsize__doc__, "calcsize(fmt) -> int\n\ --- 977,1130 ---- else num = 1; ! if (c == '(') { ! if ((itemsize = group_calcsize(&s, f, lvl+1)) < 0) ! return -1; ! } ! else if (c == ')') { ! if (lvl == 0) { ! PyErr_SetString(StructError, ! "mismatched parenthesis in struct format"); ! return -1; ! } ! *pfmt = s; ! return size; } + else { + e = getentry(c, f); + if (e == NULL) + return -1; + itemsize = e->size; + size = align(size, c, e); + } + + if (itemsize > 0) { + x = num * itemsize; + size += x; + if (x/itemsize != num || size < 0) { + PyErr_SetString(StructError, + "total struct size too long"); + return -1; + } + } + } + + if (lvl != 0) { + PyErr_SetString(StructError, + "mismatched parenthesis in struct format"); + return -1; } return size; } + static PyObject * + group_unpack(char **pfmt, char **pstart, const formatdef *f) + { + const formatdef *e; + char *str, *start, *s, *t; + char c; + int num; + PyObject *res, *v; + + res = PyList_New(0); + if (res == NULL) + return NULL; + str = start = *pstart; + s = *pfmt; + while ((c = *s++) != '\0') { + if (isspace((int)c)) + continue; + if ('0' <= c && c <= '9') { + num = c - '0'; + while ('0' <= (c = *s++) && c <= '9') + num = num*10 + (c - '0'); + if (c == '\0') + break; + } + else + num = 1; + + if (c == '(') { + do { + t = s; + v = group_unpack(&t, &str, f); + if (v == NULL || PyList_Append(res, v) < 0) + goto fail; + Py_DECREF(v); + } while (--num > 0); + s = t; + } + else if (c == ')') { + *pfmt = s; + *pstart = str; + break; + } + else { + e = getentry(c, f); + if (e == NULL) + goto fail; + str = start + align((int)(str-start), c, e); + if (num == 0 && c != 's') + continue; + + do { + if (c == 'x') { + str += num; + break; + } + if (c == 's') { + /* num is string size, not repeat count */ + v = PyString_FromStringAndSize(str, num); + if (v == NULL) + goto fail; + str += num; + num = 0; + } + else if (c == 'p') { + /* num is string buffer size, + not repeat count */ + int n = *(unsigned char*)str; + /* first byte (unsigned) is string size */ + if (n >= num) + n = num-1; + v = PyString_FromStringAndSize(str+1, n); + if (v == NULL) + goto fail; + str += num; + num = 0; + } + else { + v = e->unpack(str, e); + if (v == NULL) + goto fail; + str += e->size; + } + if (v == NULL || PyList_Append(res, v) < 0) + goto fail; + Py_DECREF(v); + } while (--num > 0); + } + } + + v = PyList_AsTuple(res); + Py_DECREF(res); + return v; + + fail: + Py_DECREF(res); + return NULL; + } + + /* calculate the size of a format string */ + + static int + calcsize(const char *fmt, const formatdef *f) + { + const char **pfmt = &fmt; + return group_calcsize(pfmt, f, 0); + } + PyDoc_STRVAR(calcsize__doc__, "calcsize(fmt) -> int\n\ *************** *** 1166,1176 **** static PyObject * struct_unpack(PyObject *self, PyObject *args) { ! const formatdef *f, *e; ! char *str, *start, *fmt, *s; ! char c; ! int len, size, num; ! PyObject *res, *v; if (!PyArg_ParseTuple(args, "ss#:unpack", &fmt, &start, &len)) return NULL; --- 1297,1305 ---- static PyObject * struct_unpack(PyObject *self, PyObject *args) { ! const formatdef *f; ! char *start, *fmt; ! int len, size; if (!PyArg_ParseTuple(args, "ss#:unpack", &fmt, &start, &len)) return NULL; *************** *** 1183,1258 **** "unpack str size does not match format"); return NULL; } ! res = PyList_New(0); ! if (res == NULL) ! return NULL; ! str = start; ! s = fmt; ! while ((c = *s++) != '\0') { ! if (isspace((int)c)) ! continue; ! if ('0' <= c && c <= '9') { ! num = c - '0'; ! while ('0' <= (c = *s++) && c <= '9') ! num = num*10 + (c - '0'); ! if (c == '\0') ! break; ! } ! else ! num = 1; ! ! e = getentry(c, f); ! if (e == NULL) ! goto fail; ! str = start + align((int)(str-start), c, e); ! if (num == 0 && c != 's') ! continue; ! ! do { ! if (c == 'x') { ! str += num; ! break; ! } ! if (c == 's') { ! /* num is string size, not repeat count */ ! v = PyString_FromStringAndSize(str, num); ! if (v == NULL) ! goto fail; ! str += num; ! num = 0; ! } ! else if (c == 'p') { ! /* num is string buffer size, ! not repeat count */ ! int n = *(unsigned char*)str; ! /* first byte (unsigned) is string size */ ! if (n >= num) ! n = num-1; ! v = PyString_FromStringAndSize(str+1, n); ! if (v == NULL) ! goto fail; ! str += num; ! num = 0; ! } ! else { ! v = e->unpack(str, e); ! if (v == NULL) ! goto fail; ! str += e->size; ! } ! if (v == NULL || PyList_Append(res, v) < 0) ! goto fail; ! Py_DECREF(v); ! } while (--num > 0); ! } ! ! v = PyList_AsTuple(res); ! Py_DECREF(res); ! return v; ! ! fail: ! Py_DECREF(res); ! return NULL; } --- 1312,1318 ---- "unpack str size does not match format"); return NULL; } ! return group_unpack(&fmt, &start, f); }