8 1.01 12 May 1999 Laurence Tratt
10 * Changed swi.error to be a class based exception rather than string based
11 * Added swi.ArgError which is generated for errors when the user passes invalid arguments to
13 * Added "errnum" attribute to swi.error, so one can now check to see what the error number was
22 #define PyBlock_Check(op) ((op)->ob_type == &PyBlockType)
25 static PyObject
*SwiError
; /* Exception swi.error */
26 static PyObject
*ArgError
; /* Exception swi.ArgError */
29 static PyObject
*swi_oserror(void)
30 { PyErr_SetString(SwiError
,e
->errmess
);
31 PyObject_SetAttrString(PyErr_Occurred(), "errnum", PyInt_FromLong(e
->errnum
));
35 static PyObject
*swi_error(char *s
)
36 { PyErr_SetString(ArgError
,s
);
43 int length
; /*length in bytes*/
47 static PyTypeObject PyBlockType
;
51 static PyObject
*PyBlock_New(PyObject
*self
,PyObject
*args
)
55 if(!PyArg_ParseTuple(args
,"i|O",&size
,&init
)) return NULL
;
57 b
=PyObject_NEW(PyBlockObject
,&PyBlockType
);
59 b
->block
=malloc(4*size
);
62 return PyErr_NoMemory();
67 { if(PyString_Check(init
))
68 { int n
=PyString_Size(init
);
69 if (n
>4*size
) n
=4*size
;
70 memcpy(b
->block
,PyString_AsString(init
),n
);
71 memset((char*)b
->block
+n
,0,4*size
-n
);
75 long *p
=(long*)b
->block
;
76 if(!PyList_Check(init
)) goto fail
;
80 { PyObject
*q
=PyList_GetItem(init
,k
);
81 if(!PyInt_Check(q
)) goto fail
;
84 for(;k
<size
;k
++) p
[k
]=0;
88 fail
:PyErr_SetString(PyExc_TypeError
,
89 "block initialiser must be string or list of integers");
94 static PyObject
*PyRegister(PyObject
*self
,PyObject
*args
)
97 if(!PyArg_ParseTuple(args
,"ii",&size
,&ptr
)) return NULL
;
99 b
=PyObject_NEW(PyBlockObject
,&PyBlockType
);
104 return (PyObject
*)b
;
107 static PyObject
*PyBlock_ToString(PyBlockObject
*self
,PyObject
*arg
)
108 { int s
=0,e
=self
->length
;
109 if(!PyArg_ParseTuple(arg
,"|ii",&s
,&e
)) return NULL
;
110 if(s
<0||e
>self
->length
||s
>e
)
111 { PyErr_SetString(PyExc_IndexError
,"block index out of range");
114 return PyString_FromStringAndSize((char*)self
->block
+s
,e
-s
);
117 static PyObject
*PyBlock_NullString(PyBlockObject
*self
,PyObject
*arg
)
118 { int s
=0,e
=self
->length
,i
;
119 char *p
=(char*)self
->block
;
120 if(!PyArg_ParseTuple(arg
,"|ii",&s
,&e
)) return NULL
;
121 if(s
<0||e
>self
->length
||s
>e
)
122 { PyErr_SetString(PyExc_IndexError
,"block index out of range");
125 for(i
=s
;i
<e
;i
++) if(p
[i
]==0) break;
126 return PyString_FromStringAndSize((char*)self
->block
+s
,i
-s
);
129 static PyObject
*PyBlock_CtrlString(PyBlockObject
*self
,PyObject
*arg
)
130 { int s
=0,e
=self
->length
,i
;
131 char *p
=(char*)self
->block
;
132 if(!PyArg_ParseTuple(arg
,"|ii",&s
,&e
)) return NULL
;
133 if(s
<0||e
>self
->length
||s
>e
)
134 { PyErr_SetString(PyExc_IndexError
,"block index out of range");
137 for(i
=s
;i
<e
;i
++) if(p
[i
]<32) break;
138 return PyString_FromStringAndSize((char*)self
->block
+s
,i
-s
);
141 static PyObject
*PyBlock_PadString(PyBlockObject
*self
,PyObject
*arg
)
142 { int s
=0,e
=self
->length
,n
,m
;
145 char *p
=(char*)self
->block
;
146 if(!PyArg_ParseTuple(arg
,"s#c|ii",&str
,&n
,&c
,&s
,&e
)) return NULL
;
147 if(s
<0||e
>self
->length
||s
>e
)
148 { PyErr_SetString(PyExc_IndexError
,"block index out of range");
153 memcpy(p
+s
,str
,n
);memset(p
+s
+n
,c
,m
-n
);
154 Py_INCREF(Py_None
);return Py_None
;
157 static PyObject
*PyBlock_BitSet(PyBlockObject
*self
,PyObject
*arg
)
159 int *p
=(int*)self
->block
;
160 if(!PyArg_ParseTuple(arg
,"iii",&i
,&x
,&y
)) return NULL
;
161 if(i
<0||i
>=self
->length
/4)
162 { PyErr_SetString(PyExc_IndexError
,"block index out of range");
166 Py_INCREF(Py_None
);return Py_None
;
169 static PyObject
*PyBlock_Resize(PyBlockObject
*self
,PyObject
*arg
)
171 if(!PyArg_ParseTuple(arg
,"i",&n
)) return NULL
;
174 { void *v
=realloc(self
->block
,4*n
);
175 if (!v
) return PyErr_NoMemory();
179 Py_INCREF(Py_None
);return Py_None
;
182 static PyObject
*PyBlock_ToFile(PyBlockObject
*self
,PyObject
*arg
)
183 { int s
=0,e
=self
->length
/4;
186 if(!PyArg_ParseTuple(arg
,"O|ii",&f
,&s
,&e
)) return NULL
;
189 { PyErr_SetString(PyExc_TypeError
, "arg must be open file");
192 fwrite((int*)(self
->block
)+s
,4,e
-s
,fp
);
193 Py_INCREF(Py_None
);return Py_None
;
196 static struct PyMethodDef PyBlock_Methods
[]=
197 { { "tostring",(PyCFunction
)PyBlock_ToString
,1},
198 { "padstring",(PyCFunction
)PyBlock_PadString
,1},
199 { "nullstring",(PyCFunction
)PyBlock_NullString
,1},
200 { "ctrlstring",(PyCFunction
)PyBlock_CtrlString
,1},
201 { "bitset",(PyCFunction
)PyBlock_BitSet
,1},
202 { "resize",(PyCFunction
)PyBlock_Resize
,1},
203 { "tofile",(PyCFunction
)PyBlock_ToFile
,1},
204 { NULL
,NULL
} /* sentinel */
207 static int block_len(PyBlockObject
*b
)
208 { return b
->length
/4;
211 static PyObject
*block_concat(PyBlockObject
*b
,PyBlockObject
*c
)
212 { PyErr_SetString(PyExc_IndexError
,"block concatenation not implemented");
216 static PyObject
*block_repeat(PyBlockObject
*b
,int i
)
217 { PyErr_SetString(PyExc_IndexError
,"block repetition not implemented");
221 static PyObject
*block_item(PyBlockObject
*b
,int i
)
222 { if(i
<0||4*i
>=b
->length
)
223 { PyErr_SetString(PyExc_IndexError
,"block index out of range");
226 return PyInt_FromLong(((long*)(b
->block
))[i
]);
229 static PyObject
*block_slice(PyBlockObject
*b
,int i
,int j
)
233 if(j
>b
->length
/4) j
=b
->length
/4;
235 { PyErr_SetString(PyExc_IndexError
,"block index out of range");
239 result
=PyList_New(n
);
240 for(k
=0;k
<n
;k
++) PyList_SetItem(result
,k
,PyInt_FromLong(p
[i
+k
]));
244 static int block_ass_item(PyBlockObject
*b
,int i
,PyObject
*v
)
245 { if(i
<0||i
>=b
->length
/4)
246 { PyErr_SetString(PyExc_IndexError
,"block index out of range");
250 { PyErr_SetString(PyExc_TypeError
,"block item must be integer");
253 ((long*)(b
->block
))[i
]=PyInt_AsLong(v
);
257 static int block_ass_slice(PyBlockObject
*b
,int i
,int j
,PyObject
*v
)
260 if(j
>b
->length
/4) j
=b
->length
/4;
262 { PyErr_SetString(PyExc_IndexError
,"block index out of range");
265 if(!PyList_Check(v
)) goto fail
;
269 { PyObject
*q
=PyList_GetItem(v
,k
);
270 if(!PyInt_Check(q
)) goto fail
;
271 p
[i
+k
]=PyInt_AsLong(q
);
273 for(;k
<j
-i
;k
++) p
[i
+k
]=0;
275 fail
:PyErr_SetString(PyExc_TypeError
,"block slice must be integer list");
279 static PySequenceMethods block_as_sequence
=
280 { (inquiry
)block_len
, /*sq_length*/
281 (binaryfunc
)block_concat
, /*sq_concat*/
282 (intargfunc
)block_repeat
, /*sq_repeat*/
283 (intargfunc
)block_item
, /*sq_item*/
284 (intintargfunc
)block_slice
, /*sq_slice*/
285 (intobjargproc
)block_ass_item
, /*sq_ass_item*/
286 (intintobjargproc
)block_ass_slice
, /*sq_ass_slice*/
289 static PyObject
*PyBlock_GetAttr(PyBlockObject
*s
,char *name
)
291 if (!strcmp(name
, "length")) return PyInt_FromLong((long)s
->length
);
292 if (!strcmp(name
, "start")) return PyInt_FromLong((long)s
->block
);
293 if (!strcmp(name
,"end")) return PyInt_FromLong(((long)(s
->block
)+s
->length
));
294 if (!strcmp(name
, "__members__"))
295 { PyObject
*list
= PyList_New(3);
297 { PyList_SetItem(list
, 0, PyString_FromString("length"));
298 PyList_SetItem(list
, 1, PyString_FromString("start"));
299 PyList_SetItem(list
, 2, PyString_FromString("end"));
300 if (PyErr_Occurred()) { Py_DECREF(list
);list
= NULL
;}
304 return Py_FindMethod(PyBlock_Methods
, (PyObject
*) s
,name
);
307 static void PyBlock_Dealloc(PyBlockObject
*b
)
318 static PyTypeObject PyBlockType
=
319 { PyObject_HEAD_INIT(&PyType_Type
)
322 sizeof(PyBlockObject
), /*tp_size*/
325 (destructor
)PyBlock_Dealloc
, /*tp_dealloc*/
327 (getattrfunc
)PyBlock_GetAttr
, /*tp_getattr*/
332 &block_as_sequence
, /*tp_as_sequence*/
339 static PyObject
*swi_swi(PyObject
*self
,PyObject
*args
)
340 { PyObject
*name
,*format
,*result
,*v
;
341 int swino
,carry
,rno
=0,j
,n
;
342 char *swiname
,*fmt
,*outfmt
;
345 if(args
==NULL
||!PyTuple_Check(args
)||(n
=PyTuple_Size(args
))<2)
346 { PyErr_BadArgument(); return NULL
;}
347 name
=PyTuple_GetItem(args
,0);
348 if(!PyArg_Parse(name
,"i",&swino
))
350 if(!PyArg_Parse(name
,"s",&swiname
)) return NULL
;
351 e
=xos_swi_number_from_string(swiname
,&swino
);
352 if(e
) return swi_oserror();
354 format
=PyTuple_GetItem(args
,1);
355 if(!PyArg_Parse(format
,"s",&fmt
)) return NULL
;
359 { case '.': rno
++;continue;
360 case ';':case 0: goto swicall
;
361 case '0':case '1':case '2':case '3':case '4':
362 case '5':case '6':case '7':case '8':case '9':
363 r
.r
[rno
++]=*fmt
-'0';continue;
364 case '-':r
.r
[rno
++]=-1;continue;
366 if(j
>=n
) return swi_error("Too few arguments");
367 v
=PyTuple_GetItem(args
,j
++);
369 { case 'i':if(!PyArg_Parse(v
,"i",&r
.r
[rno
])) return NULL
;
371 case 's':if(!PyArg_Parse(v
,"s",(char**)(&r
.r
[rno
]))) return NULL
;
373 case 'b':if(!PyArg_Parse(v
,"O",(PyObject
**)&ao
)) return NULL
;
374 if(!PyBlock_Check(v
)) return swi_error("Not a block");
375 r
.r
[rno
]=(int)(ao
->block
);
377 case 'e':if(!PyArg_Parse(v
,"O",(PyObject
**)&ao
)) return NULL
;
378 if(!PyBlock_Check(v
)) return swi_error("Not a block");
379 r
.r
[rno
]=(int)(ao
->block
)+ao
->length
;
381 default:return swi_error("Odd format character");
385 swicall
:e
=(os_error
*)_kernel_swi_c(swino
,&r
,&r
,&carry
);
386 if(e
) return swi_oserror();
387 if(*fmt
==0) { Py_INCREF(Py_None
);return Py_None
;}
389 for(outfmt
=++fmt
;*outfmt
;outfmt
++) switch(*outfmt
)
390 { case 'i':case 's':case '*':n
++;break;
392 default:return swi_error("Odd format character");
394 if(n
==0) { Py_INCREF(Py_None
);return Py_None
;}
396 { result
=PyTuple_New(n
);
397 if(!result
) return NULL
;
402 { case 'i':v
=PyInt_FromLong((long)r
.r
[rno
++]); break;
403 case 's':v
=PyString_FromString((char*)(r
.r
[rno
++])); break;
404 case '.':rno
++; continue;
405 case '*':v
=PyInt_FromLong((long)carry
); break;
409 PyTuple_SetItem(result
,j
,v
);
413 fail
:Py_DECREF(result
);return 0;
416 static PyMethodDef SwiMethods
[]=
417 { { "swi",swi_swi
,1},
418 { "block",PyBlock_New
,1},
419 { "register",PyRegister
,1},
420 { NULL
,NULL
} /* Sentinel */
425 m
= Py_InitModule("swi", SwiMethods
);
426 d
= PyModule_GetDict(m
);
427 SwiError
=PyErr_NewException("swi.error", NULL
, NULL
);
428 PyDict_SetItemString(d
,"error",SwiError
);
429 ArgError
=PyErr_NewException("swi.ArgError", NULL
, NULL
);
430 PyDict_SetItemString(d
,"ArgError",ArgError
);