Home | History | Annotate | Download | only in Modules
      1 /* swi
      2 
      3    RISC OS swi functions
      4 
      5  1.00               Chris Stretch
      6 
      7 
      8  1.01  12 May 1999  Laurence Tratt
      9 
     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
     12        functions etc
     13    * Added "errnum" attribute to swi.error, so one can now check to see what the error number was
     14 
     15  1.02  03 March 2002 Dietmar Schwertberger
     16    * Added string, integer, integers, tuple and tuples
     17 */
     18 
     19 #include "oslib/os.h"
     20 #include <kernel.h>
     21 #include "Python.h"
     22 
     23 
     24 #define PyBlock_Check(op) ((op)->ob_type == &PyBlockType)
     25 
     26 
     27 static PyObject *SwiError; /* Exception swi.error */
     28 static PyObject *ArgError; /* Exception swi.ArgError */
     29 static os_error *e;
     30 
     31 static PyObject *swi_oserror(void)
     32 { PyErr_SetString(SwiError,e->errmess);
     33   PyObject_SetAttrString(PyErr_Occurred(), "errnum", PyInt_FromLong(e->errnum));
     34   return 0;
     35 }
     36 
     37 static PyObject *swi_error(char *s)
     38 { PyErr_SetString(ArgError,s);
     39   return 0;
     40 }
     41 
     42 typedef struct
     43 { PyObject_HEAD
     44   void *block;
     45   int length; /*length in bytes*/
     46   int heap;
     47 } PyBlockObject;
     48 
     49 static PyTypeObject PyBlockType;
     50 
     51 /* block commands */
     52 
     53 static PyObject *PyBlock_New(PyObject *self,PyObject *args)
     54 { int size;
     55   PyBlockObject *b;
     56   PyObject *init=0;
     57   if(!PyArg_ParseTuple(args,"i|O",&size,&init)) return NULL;
     58   if(size<1) size=1;
     59   b=PyObject_NEW(PyBlockObject,&PyBlockType);
     60   if(!b) return NULL;
     61   b->block=malloc(4*size);
     62   if(!b->block)
     63   { Py_DECREF(b);
     64     return PyErr_NoMemory();
     65   }
     66   b->length=4*size;
     67   b->heap=1;
     68   if(init)
     69   { if(PyString_Check(init))
     70     { int n=PyString_Size(init);
     71       if (n>4*size) n=4*size;
     72       memcpy(b->block,PyString_AsString(init),n);
     73       memset((char*)b->block+n,0,4*size-n);
     74     }
     75     else
     76     { int n,k;
     77       long *p=(long*)b->block;
     78       if(!PyList_Check(init)) goto fail;
     79       n=PyList_Size(init);
     80       if (n>size) n=size;
     81       for(k=0;k<n;k++)
     82       { PyObject *q=PyList_GetItem(init,k);
     83         if(!PyInt_Check(q)) goto fail;
     84         p[k]=PyInt_AsLong(q);
     85       }
     86       for(;k<size;k++) p[k]=0;
     87     }
     88   }
     89   return (PyObject *)b;
     90   fail:PyErr_SetString(PyExc_TypeError,
     91      "block initialiser must be string or list of integers");
     92   Py_DECREF(b);
     93   return NULL;
     94 }
     95 
     96 static PyObject *PyRegister(PyObject *self,PyObject *args)
     97 { int size,ptr;
     98   PyBlockObject *b;
     99   if(!PyArg_ParseTuple(args,"ii",&size,&ptr)) return NULL;
    100   if(size<1) size=1;
    101   b=PyObject_NEW(PyBlockObject,&PyBlockType);
    102   if(!b) return NULL;
    103   b->block=(void*)ptr;
    104   b->length=4*size;
    105   b->heap=0;
    106   return (PyObject *)b;
    107 }
    108 
    109 static PyObject *PyBlock_ToString(PyBlockObject *self,PyObject *arg)
    110 { int s=0,e=self->length;
    111   if(!PyArg_ParseTuple(arg,"|ii",&s,&e)) return NULL;
    112   if(s<0||e>self->length||s>e)
    113   { PyErr_SetString(PyExc_IndexError,"block index out of range");
    114     return NULL;
    115   }
    116   return PyString_FromStringAndSize((char*)self->block+s,e-s);
    117 }
    118 
    119 static PyObject *PyBlock_NullString(PyBlockObject *self,PyObject *arg)
    120 { int s=0,e=self->length,i;
    121   char *p=(char*)self->block;
    122   if(!PyArg_ParseTuple(arg,"|ii",&s,&e)) return NULL;
    123   if(s<0||e>self->length||s>e)
    124   { PyErr_SetString(PyExc_IndexError,"block index out of range");
    125     return NULL;
    126   }
    127   for(i=s;i<e;i++) if(p[i]==0) break;
    128   return PyString_FromStringAndSize((char*)self->block+s,i-s);
    129 }
    130 
    131 static PyObject *PyBlock_CtrlString(PyBlockObject *self,PyObject *arg)
    132 { int s=0,e=self->length,i;
    133   char *p=(char*)self->block;
    134   if(!PyArg_ParseTuple(arg,"|ii",&s,&e)) return NULL;
    135   if(s<0||e>self->length||s>e)
    136   { PyErr_SetString(PyExc_IndexError,"block index out of range");
    137     return NULL;
    138   }
    139   for(i=s;i<e;i++) if(p[i]<32) break;
    140   return PyString_FromStringAndSize((char*)self->block+s,i-s);
    141 }
    142 
    143 static PyObject *PyBlock_PadString(PyBlockObject *self,PyObject *arg)
    144 { int s=0,e=self->length,n,m;
    145   char *str;
    146   char c;
    147   char *p=(char*)self->block;
    148   if(!PyArg_ParseTuple(arg,"s#c|ii",&str,&n,&c,&s,&e)) return NULL;
    149   if(s<0||e>self->length||s>e)
    150   { PyErr_SetString(PyExc_IndexError,"block index out of range");
    151     return NULL;
    152   }
    153   m=e-s;
    154   if(n>m) n=m;
    155   memcpy(p+s,str,n);memset(p+s+n,c,m-n);
    156   Py_INCREF(Py_None);return Py_None;
    157 }
    158 
    159 static PyObject *PyBlock_BitSet(PyBlockObject *self,PyObject *arg)
    160 { int i,x,y;
    161   int *p=(int*)self->block;
    162   if(!PyArg_ParseTuple(arg,"iii",&i,&x,&y)) return NULL;
    163   if(i<0||i>=self->length/4)
    164   { PyErr_SetString(PyExc_IndexError,"block index out of range");
    165     return NULL;
    166   }
    167   p[i]=(p[i]&y)^x;
    168   Py_INCREF(Py_None);return Py_None;
    169 }
    170 
    171 static PyObject *PyBlock_Resize(PyBlockObject *self,PyObject *arg)
    172 { int n;
    173   if(!PyArg_ParseTuple(arg,"i",&n)) return NULL;
    174   if(n<1) n=1;
    175   if(self->heap)
    176   { void *v=realloc(self->block,4*n);
    177     if (!v) return PyErr_NoMemory();
    178     self->block=v;
    179   }
    180   self->length=4*n;
    181   Py_INCREF(Py_None);return Py_None;
    182 }
    183 
    184 static PyObject *PyBlock_ToFile(PyBlockObject *self,PyObject *arg)
    185 { int s=0,e=self->length/4;
    186   PyObject *f;
    187   FILE *fp;
    188   if(!PyArg_ParseTuple(arg,"O|ii",&f,&s,&e)) return NULL;
    189   fp=PyFile_AsFile(f);
    190   if (!fp)
    191   { PyErr_SetString(PyExc_TypeError, "arg must be open file");
    192     return NULL;
    193   }
    194   fwrite((int*)(self->block)+s,4,e-s,fp);
    195   Py_INCREF(Py_None);return Py_None;
    196 }
    197 
    198 static struct PyMethodDef PyBlock_Methods[]=
    199 { { "tostring",(PyCFunction)PyBlock_ToString,1},
    200   { "padstring",(PyCFunction)PyBlock_PadString,1},
    201   { "nullstring",(PyCFunction)PyBlock_NullString,1},
    202   { "ctrlstring",(PyCFunction)PyBlock_CtrlString,1},
    203   { "bitset",(PyCFunction)PyBlock_BitSet,1},
    204   { "resize",(PyCFunction)PyBlock_Resize,1},
    205   { "tofile",(PyCFunction)PyBlock_ToFile,1},
    206   { NULL,NULL}		/* sentinel */
    207 };
    208 
    209 static int block_len(PyBlockObject *b)
    210 { return b->length/4;
    211 }
    212 
    213 static PyObject *block_concat(PyBlockObject *b,PyBlockObject *c)
    214 { PyErr_SetString(PyExc_IndexError,"block concatenation not implemented");
    215   return NULL;
    216 }
    217 
    218 static PyObject *block_repeat(PyBlockObject *b,Py_ssize_t i)
    219 { PyErr_SetString(PyExc_IndexError,"block repetition not implemented");
    220   return NULL;
    221 }
    222 
    223 static PyObject *block_item(PyBlockObject *b,Py_ssize_t i)
    224 { if(i<0||4*i>=b->length)
    225   { PyErr_SetString(PyExc_IndexError,"block index out of range");
    226     return NULL;
    227   }
    228   return PyInt_FromLong(((long*)(b->block))[i]);
    229 }
    230 
    231 static PyObject *block_slice(PyBlockObject *b,Py_ssize_t i,Py_ssize_t j)
    232 { Py_ssize_t n,k;
    233   long *p=b->block;
    234   PyObject *result;
    235   if(j>b->length/4) j=b->length/4;
    236   if(i<0||i>j)
    237   { PyErr_SetString(PyExc_IndexError,"block index out of range");
    238     return NULL;
    239   }
    240   n=j-i;
    241   result=PyList_New(n);
    242   for(k=0;k<n;k++) PyList_SetItem(result,k,PyInt_FromSsize_t(p[i+k]));
    243   return result;
    244 }
    245 
    246 static int block_ass_item(PyBlockObject *b,Py_ssize_t i,PyObject *v)
    247 { if(i<0||i>=b->length/4)
    248   { PyErr_SetString(PyExc_IndexError,"block index out of range");
    249     return -1;
    250   }
    251   if(!PyInt_Check(v))
    252   { PyErr_SetString(PyExc_TypeError,"block item must be integer");
    253     return -1;
    254   }
    255   ((long*)(b->block))[i]=PyInt_AsLong(v);
    256   return 0;
    257 }
    258 
    259 static int block_ass_slice(PyBlockObject *b,Py_ssize_t i,Py_ssize_t j,PyObject *v)
    260 { Py_ssize_t n,k;
    261   long *p=b->block;
    262   if(j>b->length/4) j=b->length/4;
    263   if(i<0||i>j)
    264   { PyErr_SetString(PyExc_IndexError,"block index out of range");
    265     return -1;
    266   }
    267   if(!PyList_Check(v)) goto fail;
    268   n=PyList_Size(v);
    269   if(n>j-i) n=j-i;
    270   for(k=0;k<n;k++)
    271   { PyObject *q=PyList_GetItem(v,k);
    272     if(!PyInt_Check(q)) goto fail;
    273     p[i+k]=PyInt_AsLong(q);
    274   }
    275   for(;k<j-i;k++) p[i+k]=0;
    276   return 0;
    277   fail:PyErr_SetString(PyExc_TypeError,"block slice must be integer list");
    278   return -1;
    279 }
    280 
    281 static PySequenceMethods block_as_sequence=
    282 { (inquiry)block_len,		/*sq_length*/
    283   (binaryfunc)block_concat,		/*sq_concat*/
    284   (ssizeargfunc)block_repeat,		/*sq_repeat*/
    285   (ssizeargfunc)block_item,		/*sq_item*/
    286   (ssizessizeargfunc)block_slice,		/*sq_slice*/
    287   (ssizeobjargproc)block_ass_item,	/*sq_ass_item*/
    288   (ssizessizeobjargproc)block_ass_slice,	/*sq_ass_slice*/
    289 };
    290 
    291 static PyObject *PyBlock_GetAttr(PyBlockObject *s,char *name)
    292 {
    293   if (!strcmp(name, "length")) return PyInt_FromLong((long)s->length);
    294   if (!strcmp(name, "start")) return PyInt_FromLong((long)s->block);
    295   if (!strcmp(name,"end")) return PyInt_FromLong(((long)(s->block)+s->length));
    296   if (!strcmp(name, "__members__"))
    297   { PyObject *list = PyList_New(3);
    298     if (list)
    299     { PyList_SetItem(list, 0, PyString_FromString("length"));
    300       PyList_SetItem(list, 1, PyString_FromString("start"));
    301       PyList_SetItem(list, 2, PyString_FromString("end"));
    302       if (PyErr_Occurred()) { Py_DECREF(list);list = NULL;}
    303     }
    304     return list;
    305   }
    306   return Py_FindMethod(PyBlock_Methods, (PyObject*) s,name);
    307 }
    308 
    309 static void PyBlock_Dealloc(PyBlockObject *b)
    310 {
    311     if(b->heap) {
    312         if (b->heap)
    313             ;
    314         else
    315             PyMem_DEL(b->block);
    316     }
    317   PyMem_DEL(b);
    318 }
    319 
    320 static PyTypeObject PyBlockType=
    321 { PyObject_HEAD_INIT(&PyType_Type)
    322   0,				/*ob_size*/
    323   "block",			/*tp_name*/
    324   sizeof(PyBlockObject),	/*tp_size*/
    325   0,				/*tp_itemsize*/
    326 	/* methods */
    327   (destructor)PyBlock_Dealloc,	/*tp_dealloc*/
    328   0,				/*tp_print*/
    329   (getattrfunc)PyBlock_GetAttr,	/*tp_getattr*/
    330   0,				/*tp_setattr*/
    331   0,				/*tp_compare*/
    332   0,				/*tp_repr*/
    333   0,				/*tp_as_number*/
    334   &block_as_sequence,		/*tp_as_sequence*/
    335   0,				/*tp_as_mapping*/
    336   0,                            /*tp_hash*/
    337 };
    338 
    339 /* swi commands */
    340 
    341 static PyObject *swi_swi(PyObject *self,PyObject *args)
    342 { PyObject *name,*format,*result,*v;
    343   int swino,carry,rno=0,j,n;
    344   char *swiname,*fmt,*outfmt;
    345   _kernel_swi_regs r;
    346   PyBlockObject *ao;
    347   if(args==NULL||!PyTuple_Check(args)||(n=PyTuple_Size(args))<2)
    348   { PyErr_BadArgument(); return NULL;}
    349   name=PyTuple_GetItem(args,0);
    350   if(!PyArg_Parse(name,"i",&swino))
    351   { PyErr_Clear();
    352     if(!PyArg_Parse(name,"s",&swiname)) return NULL;
    353     e=xos_swi_number_from_string(swiname,&swino);
    354     if(e) return swi_oserror();
    355   }
    356   format=PyTuple_GetItem(args,1);
    357   if(!PyArg_Parse(format,"s",&fmt)) return NULL;
    358   j=2;
    359   for(;;fmt++)
    360   { switch(*fmt)
    361     { case '.': rno++;continue;
    362       case ';':case 0: goto swicall;
    363       case '0':case '1':case '2':case '3':case '4':
    364       case '5':case '6':case '7':case '8':case '9':
    365         r.r[rno++]=*fmt-'0';continue;
    366       case '-':r.r[rno++]=-1;continue;
    367     }
    368     if(j>=n) return swi_error("Too few arguments");
    369     v=PyTuple_GetItem(args,j++);
    370     switch(*fmt)
    371     { case 'i':if(!PyArg_Parse(v,"i",&r.r[rno])) return NULL;
    372                break;
    373       case 's':if(!PyArg_Parse(v,"s",(char**)(&r.r[rno]))) return NULL;
    374                break;
    375       case 'b':if(!PyArg_Parse(v,"O",(PyObject**)&ao)) return NULL;
    376                if(!PyBlock_Check(v)) return swi_error("Not a block");
    377                r.r[rno]=(int)(ao->block);
    378                break;
    379       case 'e':if(!PyArg_Parse(v,"O",(PyObject**)&ao)) return NULL;
    380                if(!PyBlock_Check(v)) return swi_error("Not a block");
    381                r.r[rno]=(int)(ao->block)+ao->length;
    382                break;
    383       default:return swi_error("Odd format character");
    384     }
    385     rno++;
    386   }
    387   swicall:e=(os_error*)_kernel_swi_c(swino,&r,&r,&carry);
    388   if(e) return swi_oserror();
    389   if(*fmt==0) { Py_INCREF(Py_None);return Py_None;}
    390   n=0;
    391   for(outfmt=++fmt;*outfmt;outfmt++)  switch(*outfmt)
    392   { case 'i':case 's':case '*':n++;break;
    393     case '.':break;
    394     default:return swi_error("Odd format character");
    395   }
    396   if(n==0) { Py_INCREF(Py_None);return Py_None;}
    397   if(n!=1)
    398   { result=PyTuple_New(n);
    399     if(!result) return NULL;
    400   }
    401   rno=0;j=0;
    402   for(;*fmt;fmt++)
    403   {  switch(*fmt)
    404     { case 'i':v=PyInt_FromLong((long)r.r[rno++]); break;
    405       case 's':v=PyString_FromString((char*)(r.r[rno++])); break;
    406       case '.':rno++; continue;
    407       case '*':v=PyInt_FromLong((long)carry); break;
    408     }
    409     if(!v) goto fail;
    410     if(n==1) return v;
    411     PyTuple_SetItem(result,j,v);
    412     j++;
    413   }
    414   return result;
    415   fail:Py_DECREF(result);return 0;
    416 }
    417 
    418 static PyObject *swi_string(PyObject *self, PyObject *arg)
    419 { char *s;
    420   int l=-1;
    421   if(!PyArg_ParseTuple(arg,"i|i",(unsigned int *)&s, &l)) return NULL;
    422   if (l==-1)
    423     l = strlen(s);
    424   return PyString_FromStringAndSize((char*)s, l);
    425 }
    426 
    427 static char swi_string__doc__[] =
    428 "string(address[, length]) -> string\n\
    429 Read a null terminated string from the given address.";
    430 
    431 
    432 static PyObject *swi_integer(PyObject *self, PyObject *arg)
    433 { int *i;
    434 
    435   if(!PyArg_ParseTuple(arg,"i",(unsigned int *)&i))
    436     return NULL;
    437   return PyInt_FromLong(*i);
    438 }
    439 
    440 static char swi_integer__doc__[] =
    441 "integer(address) -> string\n\
    442 Read an integer from the given address.";
    443 
    444 
    445 static PyObject *swi_integers(PyObject *self, PyObject *arg)
    446 { int *i;
    447   int c=-1;
    448   PyObject *result, *result1;
    449 
    450   if(!PyArg_ParseTuple(arg,"i|i",(unsigned int *)&i, &c)) return NULL;
    451   result=PyList_New(0);
    452   if (result) {
    453     while ( c>0 || (c==-1 && *i) ) {
    454       result1 = PyInt_FromLong((long)*i);
    455       if (!result1) {
    456         Py_DECREF(result);
    457         return NULL;
    458       }
    459       if (PyList_Append(result, result1)!=0) {
    460         Py_DECREF(result);
    461         Py_DECREF(result1);
    462         return NULL;
    463       };
    464       i++;
    465       if (c!=-1)
    466         c--;
    467     }
    468   }
    469   return result;
    470 }
    471 
    472 static char swi_integers__doc__[] =
    473 "integers(address[, count]) -> string\n\
    474 Either read a null terminated list of integers or\n\
    475 a list of given length from the given address.";
    476 
    477 
    478 static PyObject *swi_tuples(PyObject *self, PyObject *arg)
    479 {
    480   unsigned char *i;         /* points to current */
    481   int c=-1, l=4, j, zero;         /* count, length, index */
    482   PyObject *result, *result1, *result11;
    483 
    484   if(!PyArg_ParseTuple(arg,"i|ii",(unsigned int *)&i, &l, &c)) return NULL;
    485   result=PyList_New(0);
    486   if (result) {
    487     while (c) {
    488       result1 = PyTuple_New(l);
    489       if (!result1) {
    490         Py_DECREF(result);
    491         return NULL;
    492       }
    493       zero = (c==-1); /* check for zeros? */
    494       for(j=0;j<l;j++) {
    495         if (zero && *i)
    496           zero = 0;   /* non-zero found */
    497         result11 = PyInt_FromLong((long)(*i));
    498         if (!result11) {
    499           Py_DECREF(result);
    500           return NULL;
    501         }
    502         PyTuple_SetItem(result1, j, result11);
    503         i++;
    504       }
    505       if (c==-1 && zero) {
    506         Py_DECREF(result1);
    507         c = 0;
    508         break;
    509       }
    510       if (PyList_Append(result, result1)!=0) {
    511         Py_DECREF(result1);
    512         Py_DECREF(result);
    513         return NULL;
    514       }
    515       if (c!=-1)
    516         c--;
    517     }
    518   }
    519   return result;
    520 }
    521 
    522 static char swi_tuples__doc__[] =
    523 "tuples(address[, length=4[, count]]) -> string\n\
    524 Either read a null terminated list of byte tuples or\n\
    525 a list of given length from the given address.";
    526 
    527 
    528 static PyObject *swi_tuple(PyObject *self, PyObject *arg)
    529 {
    530   unsigned char *i;         /* points to current */
    531   int c=1, j;
    532   PyObject *result, *result1;
    533 
    534   if(!PyArg_ParseTuple(arg,"i|i",(unsigned int *)&i, &c)) return NULL;
    535   result = PyTuple_New(c);
    536   if (!result)
    537     return NULL;
    538   for(j=0;j<c;j++) {
    539     result1 = PyInt_FromLong((long)(i[j]));
    540     if (!result1) {
    541       Py_DECREF(result);
    542       return NULL;
    543     }
    544     PyTuple_SetItem(result, j, result1);
    545   }
    546   return result;
    547 }
    548 
    549 static char swi_tuple__doc__[] =
    550 "tuple(address[, count=1]]) -> tuple\n\
    551 Read count bytes from given address.";
    552 
    553 
    554 static PyMethodDef SwiMethods[]=
    555 { { "swi", swi_swi, METH_VARARGS},
    556   { "block", PyBlock_New, METH_VARARGS},
    557   { "register", PyRegister, METH_VARARGS},
    558   { "string", swi_string, METH_VARARGS, swi_string__doc__},
    559   { "integer", swi_integer, METH_VARARGS, swi_integer__doc__},
    560   { "integers", swi_integers, METH_VARARGS, swi_integers__doc__},
    561   { "tuples", swi_tuples, METH_VARARGS, swi_tuples__doc__},
    562   { "tuple", swi_tuple, METH_VARARGS, swi_tuple__doc__},
    563   { NULL,NULL,0,NULL}		 /* Sentinel */
    564 };
    565 
    566 
    567 void initswi()
    568 { PyObject *m, *d;
    569   m = Py_InitModule("swi", SwiMethods);
    570   d = PyModule_GetDict(m);
    571   SwiError=PyErr_NewException("swi.error", NULL, NULL);
    572   PyDict_SetItemString(d,"error",SwiError);
    573   ArgError=PyErr_NewException("swi.ArgError", NULL, NULL);
    574   PyDict_SetItemString(d,"ArgError",ArgError);
    575 }
    576