source: git/Singular/newstruct.cc @ ed47aab

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