source: git/Singular/newstruct.cc @ b2aa08

jengelh-datetimespielwiese
Last change on this file since b2aa08 was b2aa08, checked in by Alexander Dreyer <alexander.dreyer@…>, 11 years ago
fix: pyobject falls back to newstruct operations
  • Property mode set to 100644
File size: 16.5 KB
Line 
1#include <ctype.h>
2
3#include "config.h"
4#include <kernel/mod2.h>
5#include <Singular/ipid.h>
6#include <Singular/blackbox.h>
7#include <Singular/lists.h>
8#include <Singular/ipid.h>
9#include <Singular/ipshell.h>
10#include <Singular/newstruct.h>
11
12struct newstruct_member_s;
13typedef struct newstruct_member_s *newstruct_member;
14struct  newstruct_member_s
15{
16  newstruct_member next;
17  char *         name;
18  int            typ;
19  int            pos;
20};
21
22struct newstruct_proc_s;
23typedef struct newstruct_proc_a *newstruct_proc;
24struct  newstruct_proc_a
25{
26  newstruct_proc next;
27  int            t; /*tok id */
28  int            args; /* number of args */
29  procinfov      p;
30};
31
32struct newstruct_desc_s
33{
34  newstruct_member member;
35  newstruct_desc   parent;
36  newstruct_proc   procs;
37  int            size; // number of mebers +1
38  int            id;   // the type id assigned to this bb
39};
40
41int newstruct_desc_size() 
42{
43  return sizeof(newstruct_desc_s);
44}
45
46char * newstruct_String(blackbox *b, void *d)
47{
48  if (d==NULL) return omStrDup("oo");
49  else
50  {
51    newstruct_desc ad=(newstruct_desc)(b->data);
52    lists l=(lists)d;
53    newstruct_member a=ad->member;
54    StringSetS("");
55    loop
56    {
57      StringAppendS(a->name);
58      char *tmp=omStrDup(StringAppendS("="));
59      if ((!RingDependend(a->typ))
60      || ((l->m[a->pos-1].data==(void *)currRing)
61         && (currRing!=NULL)))
62      {
63        if (l->m[a->pos].rtyp==LIST_CMD)
64        {
65          StringAppendS("<list>");
66        }
67        else
68        {
69          StringSetS("");
70          char *tmp2=omStrDup(l->m[a->pos].String());
71          StringSetS(tmp);
72          if ((strlen(tmp2)>80)||(strchr(tmp2,'\n')!=NULL))
73          {
74            StringAppend("<%s>",Tok2Cmdname(l->m[a->pos].rtyp));
75          }
76          else StringAppendS(tmp2);
77          omFree(tmp2);
78        }
79      }
80      else StringAppendS("??");
81      omFree(tmp);
82      if (a->next==NULL) break;
83      StringAppendS("\n");
84      if(errorreported) break;
85      a=a->next;
86    }
87    return omStrDup(StringAppendS(""));
88  }
89}
90lists lCopy_newstruct(lists L)
91{
92  lists N=(lists)omAlloc0Bin(slists_bin);
93  int n=L->nr;
94  ring save_ring=currRing;
95  N->Init(n+1);
96  for(;n>=0;n--)
97  {
98    if (RingDependend(L->m[n].rtyp))
99    {
100      assume((L->m[n-1].rtyp==RING_CMD) || (L->m[n-1].data==NULL));
101      if(L->m[n-1].data!=NULL)
102      {
103        if (L->m[n-1].data!=(void*)currRing)
104          rChangeCurrRing((ring)(L->m[n-1].data));
105        N->m[n].Copy(&L->m[n]);
106      }
107      else
108      {
109        N->m[n].rtyp=L->m[n].rtyp;
110        N->m[n].data=idrecDataInit(L->m[n].rtyp);
111      }
112    }
113    else if(L->m[n].rtyp==LIST_CMD)
114    {
115      N->m[n].rtyp=L->m[n].rtyp;
116      N->m[n].data=(void *)lCopy((lists)(L->m[n].data));
117    }
118    else if(L->m[n].rtyp>MAX_TOK)
119    {
120      N->m[n].rtyp=L->m[n].rtyp;
121      blackbox *b=getBlackboxStuff(N->m[n].rtyp);
122      N->m[n].data=(void *)b->blackbox_Copy(b,L->m[n].data);
123    }
124    else
125      N->m[n].Copy(&L->m[n]);
126  }
127  if (currRing!=save_ring) rChangeCurrRing(save_ring);
128  return N;
129}
130void * newstruct_Copy(blackbox*, void *d)
131{
132  lists n1=(lists)d;
133  return (void*)lCopy_newstruct(n1);
134}
135
136BOOLEAN newstruct_Assign(leftv l, leftv r)
137{
138  if (r->Typ()>MAX_TOK)
139  {
140    blackbox *rr=getBlackboxStuff(r->Typ());
141    if (l->Typ()!=r->Typ())
142    {
143      newstruct_desc rrn=(newstruct_desc)rr->data;
144
145      if (!rrn)
146      {
147        Werror("custom type %s(%d) cannot be assigned to newstruct %s(%d)",
148               Tok2Cmdname(r->Typ()), r->Typ(), Tok2Cmdname(l->Typ()), l->Typ());
149        return TRUE;
150      }
151
152      newstruct_desc rrp=rrn->parent;
153      while ((rrp!=NULL)&&(rrp->id!=l->Typ())) rrp=rrp->parent;
154      if (rrp!=NULL)
155      {
156        if (l->rtyp==IDHDL)
157        {
158          IDTYP((idhdl)l->data)=r->Typ();
159        }
160        else
161        {
162          l->rtyp=r->Typ();
163        }
164      }
165      else                      // unrelated types - look for custom conversion
166      {
167        sleftv tmp;
168        BOOLEAN newstruct_Op1(int, leftv, leftv);  // forward declaration
169        if (! newstruct_Op1(l->Typ(), &tmp, r))  return newstruct_Assign(l, &tmp);
170      }
171    }
172    if (l->Typ()==r->Typ())
173    {
174      if (l->Data()!=NULL)
175      {
176        lists n1=(lists)l->Data();
177        n1->Clean(); n1=NULL;
178      }
179      lists n2=(lists)r->Data();
180      n2=lCopy_newstruct(n2);
181      if (l->rtyp==IDHDL)
182      {
183        IDDATA((idhdl)l->data)=(char *)n2;
184      }
185      else
186      {
187        l->data=(void *)n2;
188      }
189      return FALSE;
190    }
191  }
192  Werror("assign %s(%d) = %s(%d)",
193        Tok2Cmdname(l->Typ()),l->Typ(),Tok2Cmdname(r->Typ()),r->Typ());
194  return TRUE;
195}
196
197BOOLEAN newstruct_Op1(int op, leftv res, leftv arg)
198{
199  // interpreter: arg is newstruct
200  blackbox *a=getBlackboxStuff(arg->Typ());
201  newstruct_desc nt=(newstruct_desc)a->data;
202  newstruct_proc p=nt->procs;
203
204  while((p!=NULL) &&( (p->t!=op) || (p->args!=1) )) p=p->next;
205
206  if (p!=NULL)
207  {
208    leftv sl;
209    sleftv tmp;
210    memset(&tmp,0,sizeof(sleftv));
211    tmp.Copy(arg);
212    idrec hh;
213    memset(&hh,0,sizeof(hh));
214    hh.id=Tok2Cmdname(p->t);
215    hh.typ=PROC_CMD;
216    hh.data.pinf=p->p;
217    sl=iiMake_proc(&hh,NULL,&tmp);
218    if (sl==NULL) return TRUE;
219    else
220    {
221      res->Copy(sl);
222      return FALSE;
223    }
224  }
225  return blackboxDefaultOp1(op,res,arg);
226}
227
228
229
230BOOLEAN newstruct_Op2(int op, leftv res, leftv a1, leftv a2)
231{
232  // interpreter: a1 or a2 is newstruct
233  blackbox *a=getBlackboxStuff(a1->Typ());
234  newstruct_desc nt;
235  lists al=(lists)a1->Data();
236  if (a!=NULL)
237  {
238    nt=(newstruct_desc)a->data;
239    switch(op)
240    {
241      case '.':
242      {
243        if (a2->name!=NULL)
244        {
245          BOOLEAN search_ring=FALSE;
246          newstruct_member nm=nt->member;
247          while ((nm!=NULL)&&(strcmp(nm->name,a2->name)!=0)) nm=nm->next;
248          if ((nm==NULL) && (strncmp(a2->name,"r_",2)==0))
249          {
250            nm=nt->member;
251            while ((nm!=NULL)&&(strcmp(nm->name,a2->name+2)!=0)) nm=nm->next;
252            if ((nm!=NULL)&&(RingDependend(nm->typ)))
253              search_ring=TRUE;
254            else
255              nm=NULL;
256          }
257          if (nm==NULL)
258          {
259            Werror("member %s nor found", a2->name);
260            return TRUE;
261          }
262          if (search_ring)
263          {
264            ring r;
265            res->rtyp=RING_CMD;
266            res->data=al->m[nm->pos-1].data;
267            r=(ring)res->data;
268            if (r==NULL) { res->data=(void *)currRing; r=currRing; }
269            if (r!=NULL) r->ref++;
270            else Werror("ring of this member is not set and no basering found");
271            return r==NULL;
272          }
273          else if (RingDependend(nm->typ))
274          {
275            if (al->m[nm->pos].data==NULL)
276            {
277              // NULL belongs to any ring
278              ring r=(ring)al->m[nm->pos-1].data;
279              if (r!=NULL)
280              {
281                r->ref--;
282                al->m[nm->pos-1].data=NULL;
283                al->m[nm->pos-1].rtyp=DEF_CMD;
284              }
285            }
286            else
287            {
288              //Print("checking ring at pos %d for dat at pos %d\n",nm->pos-1,nm->pos);
289              if ((al->m[nm->pos-1].data!=(void *)currRing)
290              &&(al->m[nm->pos-1].data!=(void*)0L))
291              {
292                Werror("different ring %lx(data) - %lx(basering)",
293                  (long unsigned)(al->m[nm->pos-1].data),(long unsigned)currRing);
294                return TRUE;
295              }
296            }
297            if ((currRing!=NULL)&&(al->m[nm->pos-1].data==NULL))
298            {
299              // remember the ring, if not already set
300              al->m[nm->pos-1].data=(void *)currRing;
301              al->m[nm->pos-1].rtyp=RING_CMD;
302              currRing->ref++;
303            }
304          }
305          Subexpr r=(Subexpr)omAlloc0Bin(sSubexpr_bin);
306          r->start = nm->pos+1;
307          memcpy(res,a1,sizeof(sleftv));
308          memset(a1,0,sizeof(sleftv));
309          if (res->e==NULL) res->e=r;
310          else
311          {
312            Subexpr sh=res->e;
313            while (sh->next != NULL) sh=sh->next;
314            sh->next=r;
315          }
316          return FALSE;
317        }
318        else
319        {
320          WerrorS("name expected");
321          return TRUE;
322        }
323      }
324    }
325  }
326  else
327  {
328    a=getBlackboxStuff(a2->Typ());
329    nt=(newstruct_desc)a->data;
330    al=(lists)a2->Data();
331  }
332  newstruct_proc p=nt->procs;
333  while((p!=NULL) && ( (p->t!=op) || (p->args!=2) )) p=p->next;
334  if (p!=NULL)
335  {
336    leftv sl;
337    sleftv tmp;
338    memset(&tmp,0,sizeof(sleftv));
339    tmp.Copy(a1);
340    tmp.next=(leftv)omAlloc0(sizeof(sleftv));
341    tmp.next->Copy(a2);
342    idrec hh;
343    memset(&hh,0,sizeof(hh));
344    hh.id=Tok2Cmdname(p->t);
345    hh.typ=PROC_CMD;
346    hh.data.pinf=p->p;
347    sl=iiMake_proc(&hh,NULL,&tmp);
348    if (sl==NULL) return TRUE;
349    else
350    {
351      res->Copy(sl);
352      return FALSE;
353    }
354  }
355  return blackboxDefaultOp2(op,res,a1,a2);
356}
357
358// BOOLEAN opM(int op, leftv res, leftv args)
359BOOLEAN newstruct_OpM(int op, leftv res, leftv args)
360{
361  // interpreter: args->1. arg is newstruct
362  blackbox *a=getBlackboxStuff(args->Typ());
363  newstruct_desc nt=(newstruct_desc)a->data;
364  switch(op)
365  {
366    case STRING_CMD:
367    {
368      res->data=(void *)a->blackbox_String(a,args->Data());
369      res->rtyp=STRING_CMD;
370      return FALSE;
371    }
372    default:
373      break;
374  }
375  newstruct_proc p=nt->procs;
376 
377  while((p!=NULL) &&( (p->t!=op) || (p->args!=4) )) p=p->next;
378
379  if (p!=NULL)
380  {
381    leftv sl;
382    sleftv tmp;
383    memset(&tmp,0,sizeof(sleftv));
384    tmp.Copy(args);
385    idrec hh;
386    memset(&hh,0,sizeof(hh));
387    hh.id=Tok2Cmdname(p->t);
388    hh.typ=PROC_CMD;
389    hh.data.pinf=p->p;
390    sl=iiMake_proc(&hh,NULL,&tmp);
391    if (sl==NULL) return TRUE;
392    else
393    {
394      res->Copy(sl);
395      return FALSE;
396    }
397  }
398  return blackbox_default_OpM(op,res,args);
399}
400
401void lClean_newstruct(lists l)
402{
403  if (l->nr>=0)
404  {
405    int i;
406    ring r=NULL;
407    for(i=l->nr;i>=0;i--)
408    {
409      if ((i>0) && (l->m[i-1].rtyp==RING_CMD))
410        r=(ring)(l->m[i-1].data);
411      else
412        r=NULL;
413      l->m[i].CleanUp(r);
414    }
415    omFreeSize((ADDRESS)l->m, (l->nr+1)*sizeof(sleftv));
416    l->nr=-1;
417  }
418  omFreeBin((ADDRESS)l,slists_bin);
419}
420
421void newstruct_destroy(blackbox *b, void *d)
422{
423  if (d!=NULL)
424  {
425    lists n=(lists)d;
426    lClean_newstruct(n);
427  }
428}
429
430void *newstruct_Init(blackbox *b)
431{
432  newstruct_desc n=(newstruct_desc)b->data;
433  lists l=(lists)omAlloc0Bin(slists_bin);
434  l->Init(n->size);
435  newstruct_member nm=n->member;
436  while (nm!=NULL)
437  {
438    l->m[nm->pos].rtyp=nm->typ;
439    l->m[nm->pos].data=idrecDataInit(nm->typ);
440    nm=nm->next;
441  }
442  return l;
443}
444
445BOOLEAN newstruct_Check(blackbox *b, void *d)
446{
447  newstruct_desc n=(newstruct_desc)b->data;
448  lists l=(lists)d;
449  newstruct_member nm=n->member;
450  while (nm!=NULL)
451  {
452    if ((l->m[nm->pos].rtyp!=nm->typ)
453    &&( nm->typ!=DEF_CMD))
454    {
455      Werror("type change in member %s (%s(%d) -> %s(%d))",nm->name,
456          Tok2Cmdname(nm->typ),nm->typ,
457          Tok2Cmdname(l->m[nm->pos].rtyp),l->m[nm->pos].rtyp);
458      return TRUE;
459    }
460    nm=nm->next;
461  }
462  return FALSE;
463}
464
465BOOLEAN newstruct_serialize(blackbox *b, void *d, si_link f)
466{
467  newstruct_desc dd=(newstruct_desc)b->data;
468  sleftv l;
469  memset(&l,0,sizeof(l));
470  l.rtyp=STRING_CMD;
471  l.data=(void*)getBlackboxName(dd->id);
472  f->m->Write(f, &l);
473  lists ll=(lists)d;
474  memset(&l,0,sizeof(l));
475  l.rtyp=LIST_CMD;
476  l.data=ll;
477  f->m->Write(f, &l);
478  return FALSE;
479}
480
481BOOLEAN newstruct_deserialize(blackbox **b, void **d, si_link f)
482{
483  // newstruct is serialiazed as a list,
484  // just read a list and take data,
485  // rtyp must be set correctly (to the blackbox id) by routine calling
486  // newstruct_deserialize
487  leftv l=f->m->Read(f);
488  //newstruct_desc n=(newstruct_desc)b->data;
489  //TODO: check compatibility of list l->data with description in n
490  *d=l->data;
491  return FALSE;
492}
493
494void newstruct_Print(blackbox *b,void *d)
495{
496  newstruct_desc dd=(newstruct_desc)b->data;
497  newstruct_proc p=dd->procs;
498  while((p!=NULL)&&(p->t!=PRINT_CMD))
499    p=p->next;
500  if (p!=NULL)
501  {
502    leftv sl;
503    sleftv tmp;
504    memset(&tmp,0,sizeof(tmp));
505    tmp.rtyp=dd->id;
506    tmp.data=(void*)newstruct_Copy(b,d);
507    idrec hh;
508    memset(&hh,0,sizeof(hh));
509    hh.id=Tok2Cmdname(p->t);
510    hh.typ=PROC_CMD;
511    hh.data.pinf=p->p;
512    sl=iiMake_proc(&hh,NULL,&tmp);
513  }
514  else
515    blackbox_default_Print(b,d);
516}
517void newstruct_setup(const char *n, newstruct_desc d )
518{
519  blackbox *b=(blackbox*)omAlloc0(sizeof(blackbox));
520  // all undefined entries will be set to default in setBlackboxStuff
521  // the default Print is quite useful,
522  // all other are simply error messages
523  b->blackbox_destroy=newstruct_destroy;
524  b->blackbox_String=newstruct_String;
525  b->blackbox_Print=newstruct_Print;//blackbox_default_Print;
526  b->blackbox_Init=newstruct_Init;
527  b->blackbox_Copy=newstruct_Copy;
528  b->blackbox_Assign=newstruct_Assign;
529  b->blackbox_Op1=newstruct_Op1;
530  b->blackbox_Op2=newstruct_Op2;
531  //b->blackbox_Op3=blackbox_default_Op3;
532  b->blackbox_OpM=newstruct_OpM;
533  b->blackbox_Check=newstruct_Check;
534  b->blackbox_serialize=newstruct_serialize;
535  b->blackbox_deserialize=newstruct_deserialize;
536  b->data=d;
537  b->properties=1; // list_like
538  int rt=setBlackboxStuff(b,n);
539  d->id=rt;
540  //Print("create type %d (%s)\n",rt,n);
541}
542
543static newstruct_desc scanNewstructFromString(const char *s, newstruct_desc res)
544{
545  char *ss=omStrDup(s);
546  char *p=ss;
547  char *start;
548  int t;
549  char c;
550  newstruct_member elem;
551
552  idhdl save_ring=currRingHdl;
553  currRingHdl=(idhdl)1; // fake ring detection
554  loop
555  {
556    // read type:
557    while (*p==' ') p++;
558    start=p;
559    while (isalpha(*p)) p++;
560    *p='\0';
561    IsCmd(start,t);
562    if (t==0)
563    {
564      Werror("unknown type `%s`",start);
565      omFree(ss);
566      omFree(res);
567      currRingHdl=save_ring;
568      return NULL;
569    }
570    if (RingDependend(t))
571      res->size++;    // one additional field for the ring (before the data)
572    //Print("found type %s at real-pos %d",start,res->size);
573    elem=(newstruct_member)omAlloc0(sizeof(*elem));
574    // read name:
575    p++;
576    while (*p==' ') p++;
577    start=p;
578    while (isalpha(*p)) p++;
579    c=*p;
580    *p='\0';
581    elem->typ=t;
582    elem->pos=res->size;
583    if (*start=='\0') /*empty name*/
584    {
585      WerrorS("empty name for element");
586      goto error_in_newstruct_def;
587    }
588    elem->name=omStrDup(start);
589    //Print(" name:%s\n",start);
590    elem->next=res->member;
591    res->member=elem;
592    res->size++;
593
594    // next ?
595    *p=c;
596    while (*p==' ') p++;
597    if (*p!=',')
598    {
599      if (*p!='\0')
600      {
601        Werror("unknown character in newstruct:>>%s<<",p);
602        goto error_in_newstruct_def;
603      }
604      break; // end-of-list
605    }
606    p++;
607  }
608  omFree(ss);
609  currRingHdl=save_ring;
610  //Print("new type with %d elements\n",res->size);
611  return res;
612error_in_newstruct_def:
613   omFree(elem);
614   omFree(ss);
615   omFree(res);
616   currRingHdl=save_ring;
617   return NULL;
618}
619newstruct_desc newstructFromString(const char *s)
620{
621  newstruct_desc res=(newstruct_desc)omAlloc0(sizeof(*res));
622  res->size=0;
623
624  return scanNewstructFromString(s,res);
625}
626newstruct_desc newstructChildFromString(const char *parent, const char *s)
627{
628  // find parent:
629  int parent_id=0;
630  blackboxIsCmd(parent,parent_id);
631  if (parent_id<MAX_TOK)
632  {
633    Werror(">>%s< not found",parent);
634    return NULL;
635  }
636  blackbox *parent_bb=getBlackboxStuff(parent_id);
637  // check for the correct type:
638  if (parent_bb->blackbox_destroy!=newstruct_destroy)
639  {
640    Werror(">>%s< is not a user defined type",parent);
641    return NULL;
642  }
643  // setup for scanNewstructFromString:
644  newstruct_desc res=(newstruct_desc)omAlloc0(sizeof(*res));
645  newstruct_desc parent_desc=(newstruct_desc)parent_bb->data;
646  res->size=parent_desc->size;
647  res->member=parent_desc->member;
648  res->parent=parent_desc;
649
650  return scanNewstructFromString(s,res);
651}
652void newstructShow(newstruct_desc d)
653{
654  newstruct_member elem;
655  Print("id: %d\n",d->id);
656  elem=d->member;
657  while (elem!=NULL)
658  {
659    Print(">>%s<< at pos %d, type %d\n",elem->name,elem->pos,elem->typ);
660    elem=elem->next;
661  }
662}
663
664BOOLEAN newstruct_set_proc(const char *bbname,const char *func, int args,procinfov pr)
665{
666  int id=0;
667  blackboxIsCmd(bbname,id);
668  blackbox *bb=getBlackboxStuff(id);
669  newstruct_desc desc=(newstruct_desc)bb->data;
670  newstruct_proc p=(newstruct_proc)omAlloc(sizeof(*p));
671  p->next=desc->procs; desc->procs=p;
672
673  idhdl save_ring=currRingHdl;
674  currRingHdl=(idhdl)1; // fake ring detection
675
676  if(!IsCmd(func,p->t))
677  {
678    int t=0;
679    if (func[1]=='\0') p->t=func[0];
680    else if((t=iiOpsTwoChar(func))!=0)
681    {
682      p->t=t;
683    }
684    else
685    {
686      Werror(">>%s<< is not a kernel command",func);
687      currRingHdl = save_ring;
688      return TRUE;
689    }
690  }
691  p->args=args;
692  p->p=pr; pr->ref++;
693  currRingHdl = save_ring;
694  return FALSE;
695}
Note: See TracBrowser for help on using the repository browser.