]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
struct: pack/unpack binary structs; fcntl: fcntl(), ioctl().
authorGuido van Rossum <guido@python.org>
Mon, 17 Aug 1992 08:55:12 +0000 (08:55 +0000)
committerGuido van Rossum <guido@python.org>
Mon, 17 Aug 1992 08:55:12 +0000 (08:55 +0000)
Modules/fcntlmodule.c [new file with mode: 0644]
Modules/structmodule.c [new file with mode: 0644]

diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c
new file mode 100644 (file)
index 0000000..d4d48f8
--- /dev/null
@@ -0,0 +1,146 @@
+/***********************************************************
+Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its 
+documentation for any purpose and without fee is hereby granted, 
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in 
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* fcntl module */
+
+#include "allobjects.h"
+#include "modsupport.h"
+
+
+/* fcntl(fd, opt, [arg]) */
+
+static object *
+fcntl_fcntl(self, args)
+       object *self; /* Not used */
+       object *args;
+{
+       int fd;
+       int code;
+       int arg;
+       int ret;
+       char *str;
+       int len;
+       char buf[1024];
+
+       if (getargs(args, "(iis#)", &fd, &code, &str, &len)) {
+               if (len > sizeof buf) {
+                       err_setstr(ValueError, "fcntl string arg too long");
+                       return NULL;
+               }
+               memcpy(buf, str, len);
+               if (fcntl(fd, code, buf) < 0) {
+                       err_errno(IOError);
+                       return NULL;
+               }
+               return newsizedstringobject(buf, len);
+       }
+
+       err_clear();
+       if (getargs(args, "(ii)", &fd, &code))
+               arg = 0;
+       else {
+               err_clear();
+               if (!getargs(args, "(iii)", &fd, &code, &arg))
+                       return NULL;
+       }
+       ret = fcntl(fd, code, arg);
+       if (ret < 0) {
+               err_errno(IOError);
+               return NULL;
+       }
+       return newintobject((long)ret);
+}
+
+
+/* ioctl(fd, opt, [arg]) */
+
+static object *
+fcntl_ioctl(self, args)
+       object *self; /* Not used */
+       object *args;
+{
+       int fd;
+       int code;
+       int arg;
+       int ret;
+       char *str;
+       int len;
+       char buf[1024];
+
+       if (getargs(args, "(iis#)", &fd, &code, &str, &len)) {
+               if (len > sizeof buf) {
+                       err_setstr(ValueError, "ioctl string arg too long");
+                       return NULL;
+               }
+               memcpy(buf, str, len);
+               if (ioctl(fd, code, buf) < 0) {
+                       err_errno(IOError);
+                       return NULL;
+               }
+               return newsizedstringobject(buf, len);
+       }
+
+       err_clear();
+       if (getargs(args, "(ii)", &fd, &code))
+               arg = 0;
+       else {
+               err_clear();
+               if (!getargs(args, "(iii)", &fd, &code, &arg))
+                       return NULL;
+       }
+       ret = ioctl(fd, code, arg);
+       if (ret < 0) {
+               err_errno(IOError);
+               return NULL;
+       }
+       return newintobject((long)ret);
+}
+
+
+/* List of functions */
+
+static struct methodlist fcntl_methods[] = {
+       {"fcntl",       fcntl_fcntl},
+       {"ioctl",       fcntl_ioctl},
+       {NULL,          NULL}           /* sentinel */
+};
+
+
+/* Module initialisation */
+
+void
+initfcntl()
+{
+       object *m, *d;
+
+       /* Create the module and add the functions */
+       m = initmodule("fcntl", fcntl_methods);
+
+       /* Add some symbolic constants to the module */
+       d = getmoduledict(m);
+
+       /* Check for errors */
+       if (err_occurred())
+               fatal("can't initialize module fcntl");
+}
diff --git a/Modules/structmodule.c b/Modules/structmodule.c
new file mode 100644 (file)
index 0000000..61122e4
--- /dev/null
@@ -0,0 +1,447 @@
+/***********************************************************
+Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its 
+documentation for any purpose and without fee is hereby granted, 
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in 
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* struct module -- pack values into and (out of) strings */
+
+#include "allobjects.h"
+#include "modsupport.h"
+
+static object *StructError;
+
+
+/* Define various structs to figure out the alignments of types */
+
+typedef struct { char c; short x; } s_short;
+typedef struct { char c; int x; } s_int;
+typedef struct { char c; long x; } s_long;
+typedef struct { char c; float x; } s_float;
+typedef struct { char c; double x; } s_double;
+
+#define SHORT_ALIGN (sizeof(s_short) - sizeof(short))
+#define INT_ALIGN (sizeof(s_int) - sizeof(int))
+#define LONG_ALIGN (sizeof(s_long) - sizeof(long))
+#define FLOAT_ALIGN (sizeof(s_float) - sizeof(float))
+#define DOUBLE_ALIGN (sizeof(s_double) - sizeof(double))
+
+
+/* Align a size according to a format code */
+
+static int
+align(size, c)
+       int size;
+       int c;
+{
+       int a;
+
+       switch (c) {
+       case 'h': a = SHORT_ALIGN; break;
+       case 'i': a = INT_ALIGN; break;
+       case 'l': a = LONG_ALIGN; break;
+       case 'f': a = FLOAT_ALIGN; break;
+       case 'd': a = DOUBLE_ALIGN; break;
+       default: return size;
+       }
+       return (size + a - 1) / a * a;
+}
+
+
+/* calculate the size of a format string */
+
+static int
+calcsize(fmt)
+       char *fmt;
+{
+       char *s;
+       char c;
+       int size,  num, itemsize, x;
+
+       s = fmt;
+       size = 0;
+       while ((c = *s++) != '\0') {
+               if ('0' <= c && c <= '9') {
+                       num = c - '0';
+                       while ('0' <= (c = *s++) && c <= '9') {
+                               x = num*10 + (c - '0');
+                               if (x/10 != num) {
+                                       err_setstr(StructError,
+                                                  "int overflow in fmt");
+                                       return -1;
+                               }
+                               num = x;
+                       }
+                       if (c == '\0')
+                               break;
+               }
+               else
+                       num = 1;
+               
+               size = align(size, c);
+               
+               switch (c) {
+                       
+               case 'x': /* pad byte */
+               case 'b': /* byte-sized int */
+               case 'c': /* char */
+                       itemsize = 1;
+                       break;
+
+               case 'h': /* short ("half-size)" int */
+                       itemsize = sizeof(short);
+                       break;
+
+               case 'i': /* natural-size int */
+                       itemsize = sizeof(int);
+                       break;
+
+               case 'l': /* long int */
+                       itemsize = sizeof(long);
+                       break;
+
+               case 'f': /* float */
+                       itemsize = sizeof(float);
+                       break;
+
+               case 'd': /* double */
+                       itemsize = sizeof(double);
+                       break;
+
+               default:
+                       err_setstr(StructError, "bad char in fmt");
+                       return -1;
+
+               }
+               
+               x = num * itemsize;
+               size += x;
+               if (x/itemsize != num || size < 0) {
+                       err_setstr(StructError, "total struct size too long");
+                       return -1;
+               }
+                       
+       }
+
+       return size;
+}
+
+
+/* pack(fmt, v1, v2, ...) --> string */
+
+static object *
+struct_calcsize(self, args)
+       object *self; /* Not used */
+       object *args;
+{
+       char *fmt;
+       int size;
+
+       if (!getargs(args, "s", &fmt))
+               return NULL;
+       size = calcsize(fmt);
+       if (size < 0)
+               return NULL;
+       return newintobject((long)size);
+}
+
+
+/* pack(fmt, v1, v2, ...) --> string */
+
+static object *
+struct_pack(self, args)
+       object *self; /* Not used */
+       object *args;
+{
+       object *format, *result, *v;
+       char *fmt;
+       int size, num;
+       int i, n;
+       char *s, *res, *restart;
+       char c;
+       long ival;
+       double fval;
+
+       if (args == NULL || !is_tupleobject(args) ||
+           (n = gettuplesize(args)) < 1) {
+               err_badarg();
+               return NULL;
+       }
+       format = gettupleitem(args, 0);
+       if (!getargs(format, "s", &fmt))
+               return NULL;
+       size = calcsize(fmt);
+       if (size < 0)
+               return NULL;
+       result = newsizedstringobject((char *)NULL, size);
+       if (result == NULL)
+               return NULL;
+
+       s = fmt;
+       i = 1;
+       res = restart = getstringvalue(result);
+
+       while ((c = *s++) != '\0') {
+               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;
+
+               res = restart + align((int)(res-restart), c);
+
+               while (--num >= 0) {
+                       switch (c) {
+
+                       case 'x': /* pad byte */
+                               *res++ = '\0';
+                               break;
+
+                       case 'l':
+                       case 'i':
+                       case 'h':
+                       case 'b':
+                               if (i >= n) {
+                                       err_setstr(StructError,
+                                          "insufficient arguments to pack");
+                                       goto fail;
+                               }
+                               v = gettupleitem(args, i++);
+                               if (!is_intobject(v)) {
+                                       err_setstr(StructError,
+                                          "bad argument type to pack");
+                                       goto fail;
+                               }
+                               ival = getintvalue(v);
+                               switch (c) {
+                               case 'b':
+                                       *res++ = ival;
+                                       break;
+                               case 'h':
+                                       *(short*)res = ival;
+                                       res += sizeof(short);
+                                       break;
+                               case 'i':
+                                       *(int*)res = ival;
+                                       res += sizeof(int);
+                                       break;
+                               case 'l':
+                                       *(long*)res = ival;
+                                       res += sizeof(long);
+                                       break;
+                               }
+                               break;
+
+                       case 'c':
+                               if (i >= n) {
+                                       err_setstr(StructError,
+                                          "insufficient arguments to pack");
+                                       goto fail;
+                               }
+                               v = gettupleitem(args, i++);
+                               if (!is_stringobject(v) ||
+                                   getstringsize(v) != 1) {
+                                       err_setstr(StructError,
+                                          "bad argument type to pack");
+                                       goto fail;
+                               }
+                               *res++ = getstringvalue(v)[0];
+                               break;
+
+                       case 'd':
+                       case 'f':
+                               if (i >= n) {
+                                       err_setstr(StructError,
+                                          "insufficient arguments to pack");
+                                       goto fail;
+                               }
+                               v = gettupleitem(args, i++);
+                               if (!is_floatobject(v)) {
+                                       err_setstr(StructError,
+                                          "bad argument type to pack");
+                                       goto fail;
+                               }
+                               fval = getfloatvalue(v);
+                               switch (c) {
+                               case 'f':
+                                       *(float*)res = (float)fval;
+                                       res += sizeof(float);
+                                       break;
+                               case 'd':
+                                       *(double*)res = fval;
+                                       res += sizeof(double);
+                                       break;
+                               }
+                               break;
+
+                       default:
+                               err_setstr(StructError, "bad char in fmt");
+                               goto fail;
+
+                       }
+               }
+       }
+
+       if (i < n) {
+               err_setstr(StructError, "too many arguments for pack fmt");
+               goto fail;
+       }
+
+       return result;
+
+ fail:
+       DECREF(result);
+       return NULL;
+}
+
+
+/* unpack(fmt, string) --> (v1, v2, ...) */
+
+static object *
+struct_unpack(self, args)
+       object *self; /* Not used */
+       object *args;
+{
+       char *str, *start, *fmt, *s;
+       char c;
+       int len, size, num, x;
+       object *res, *v;
+
+       if (!getargs(args, "(ss#)", &fmt, &start, &len))
+               return NULL;
+       size = calcsize(fmt);
+       if (size != len) {
+               err_setstr(StructError, "unpack str size does not match fmt");
+               return NULL;
+       }
+       res = newlistobject(0);
+       if (res == NULL)
+               return NULL;
+       str = start;
+       s = fmt;
+       while ((c = *s++) != '\0') {
+               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;
+
+               str = start + align((int)(str-start), c);
+
+               while (--num >= 0) {
+                       switch (c) {
+
+                       case 'x':
+                               str++;
+                               continue;
+
+                       case 'b':
+                               x = *str++;
+                               if (x >= 128)
+                                       x -= 256;
+                               v = newintobject((long)x);
+                               break;
+
+                       case 'c':
+                               v = newsizedstringobject(str, 1);
+                               str++;
+                               break;
+
+                       case 'h':
+                               v = newintobject((long)*(short*)str);
+                               str += sizeof(short);
+                               break;
+
+                       case 'i':
+                               v = newintobject((long)*(int*)str);
+                               str += sizeof(int);
+                               break;
+
+                       case 'l':
+                               v = newintobject(*(long*)str);
+                               str += sizeof(long);
+                               break;
+
+                       case 'f':
+                               v = newfloatobject((double)*(float*)str);
+                               str += sizeof(float);
+                               break;
+
+                       case 'd':
+                               v = newfloatobject(*(double*)str);
+                               str += sizeof(double);
+                               break;
+
+                       default:
+                               err_setstr(StructError, "bad char in fmt");
+                               goto fail;
+
+                       }
+                       if (v == NULL || addlistitem(res, v) < 0)
+                               goto fail;
+                       DECREF(v);
+               }
+       }
+
+       return res;
+
+ fail:
+       DECREF(res);
+       return NULL;
+}
+
+/* List of functions */
+
+static struct methodlist struct_methods[] = {
+       {"calcsize",    struct_calcsize},
+       {"pack",        struct_pack,    1/*varargs*/},
+       {"unpack",      struct_unpack},
+       {NULL,          NULL}           /* sentinel */
+};
+
+
+/* Module initialization */
+
+void
+initstruct()
+{
+       object *m, *d;
+
+       /* Create the module and add the functions */
+       m = initmodule("struct", struct_methods);
+
+       /* Add some symbolic constants to the module */
+       d = getmoduledict(m);
+       StructError = newstringobject("struct.error");
+       dictinsert(d, "error", StructError);
+
+       /* Check for errors */
+       if (err_occurred())
+               fatal("can't initialize module struct");
+}