mirror of
https://github.com/python/cpython.git
synced 2024-11-27 03:45:08 +08:00
struct: pack/unpack binary structs; fcntl: fcntl(), ioctl().
This commit is contained in:
parent
94390a4eaf
commit
0297512a08
146
Modules/fcntlmodule.c
Normal file
146
Modules/fcntlmodule.c
Normal file
@ -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");
|
||||
}
|
447
Modules/structmodule.c
Normal file
447
Modules/structmodule.c
Normal file
@ -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");
|
||||
}
|
Loading…
Reference in New Issue
Block a user