source: git/Singular/newstruct.cc @ 90707f

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