source: git/Singular/newstruct.cc @ b311aa

spielwiese
Last change on this file since b311aa was b311aa, checked in by Hans Schoenemann <hannes@…>, 12 years ago
fix: allow blackbox within newstruct (from master)
  • Property mode set to 100644
File size: 12.0 KB
Line 
1#include <ctype.h>
2
3#include <kernel/mod2.h>
4#include <Singular/ipid.h>
5#include <Singular/blackbox.h>
6#include <Singular/lists.h>
7#include <Singular/ipid.h>
8#include <Singular/ipshell.h>
9#include <Singular/newstruct.h>
10
11struct newstruct_member_s;
12typedef struct newstruct_member_s *newstruct_member;
13struct  newstruct_member_s
14{
15  newstruct_member next;
16  char *         name;
17  int            typ;
18  int            pos;
19};
20
21struct newstruct_desc_s
22{
23  newstruct_member member;
24  newstruct_desc   parent;
25  int            size; // number of mebers +1
26  int            id;   // the type id assigned to this bb
27};
28
29
30char * newstruct_String(blackbox *b, void *d)
31{
32  if (d==NULL) return omStrDup("oo");
33  else
34  {
35    newstruct_desc ad=(newstruct_desc)(b->data);
36    lists l=(lists)d;
37    newstruct_member a=ad->member;
38    StringSetS("");
39    loop
40    {
41      StringAppendS(a->name);
42      char *tmp=omStrDup(StringAppendS("="));
43      if ((!RingDependend(a->typ))
44      || ((l->m[a->pos-1].data==(void *)currRing)
45         && (currRing!=NULL)))
46      {
47        if (l->m[a->pos].rtyp==LIST_CMD)
48        {
49          StringAppendS("<list>");
50        }
51        else
52        {
53          StringSetS("");
54          char *tmp2=omStrDup(l->m[a->pos].String());
55          StringSetS(tmp);
56          if ((strlen(tmp2)>80)||(strchr(tmp2,'\n')!=NULL))
57          {
58            StringAppend("<%s>",Tok2Cmdname(l->m[a->pos].rtyp));
59          }
60          else StringAppendS(tmp2);
61          omFree(tmp2);
62        }
63      }
64      else StringAppendS("??");
65      omFree(tmp);
66      if (a->next==NULL) break;
67      StringAppendS("\n");
68      if(errorreported) break;
69      a=a->next;
70    }
71    return omStrDup(StringAppendS(""));
72  }
73}
74lists lCopy_newstruct(lists L)
75{
76  lists N=(lists)omAlloc0Bin(slists_bin);
77  int n=L->nr;
78  ring save_ring=currRing;
79  N->Init(n+1);
80  for(;n>=0;n--)
81  {
82    if (RingDependend(L->m[n].rtyp))
83    {
84      assume((L->m[n-1].rtyp==RING_CMD) || (L->m[n-1].data==NULL));
85      if(L->m[n-1].data!=NULL)
86      {
87        if (L->m[n-1].data!=(void*)currRing)
88          rChangeCurrRing((ring)(L->m[n-1].data));
89        N->m[n].Copy(&L->m[n]);
90      }
91      else
92      {
93        N->m[n].rtyp=L->m[n].rtyp;
94        N->m[n].data=idrecDataInit(L->m[n].rtyp);
95      }
96    }
97    else if(L->m[n].rtyp>MAX_TOK)
98    {
99      N->m[n].rtyp=L->m[n].rtyp;
100      blackbox *b=getBlackboxStuff(N->m[n].rtyp);
101      N->m[n].data=(void *)b->blackbox_Copy(b,L->m[n].data);
102    }
103    else if(L->m[n].rtyp==LIST_CMD)
104    {
105      N->m[n].rtyp=L->m[n].rtyp;
106      N->m[n].data=(void *)lCopy((lists)(L->m[n].data));
107    }
108    else
109      N->m[n].Copy(&L->m[n]);
110  }
111  if (currRing!=save_ring) rChangeCurrRing(save_ring);
112  return N;
113}
114void * newstruct_Copy(blackbox*b, void *d)
115{
116  lists n1=(lists)d;
117  return (void*)lCopy_newstruct(n1);
118}
119
120BOOLEAN newstruct_Assign(leftv l, leftv r)
121{
122  blackbox *ll=getBlackboxStuff(l->Typ());
123  if (r->Typ()>MAX_TOK)
124  {
125    blackbox *rr=getBlackboxStuff(r->Typ());
126    if (l->Typ()!=r->Typ())
127    {
128      newstruct_desc rrn=(newstruct_desc)rr->data;
129      newstruct_desc rrp=rrn->parent;
130      while ((rrp!=NULL)&&(rrp->id!=l->Typ())) rrp=rrp->parent;
131      if (rrp!=NULL)
132      {
133        if (l->rtyp==IDHDL)
134        {
135          IDTYP((idhdl)l->data)=r->Typ();
136        }
137        else
138        {
139          l->rtyp=r->Typ();
140        }
141      }
142    }
143    if (l->Typ()==r->Typ())
144    {
145      if (l->Data()!=NULL)
146      {
147        lists n1=(lists)l->Data();
148        n1->Clean(); n1=NULL;
149      }
150      lists n2=(lists)r->Data();
151      n2=lCopy_newstruct(n2);
152      if (l->rtyp==IDHDL)
153      {
154        IDDATA((idhdl)l->data)=(char *)n2;
155      }
156      else
157      {
158        l->data=(void *)n2;
159      }
160      return FALSE;
161    }
162  }
163  Werror("assign %s(%d) = %s(%d)",
164        Tok2Cmdname(l->Typ()),l->Typ(),Tok2Cmdname(r->Typ()),r->Typ());
165  return TRUE;
166}
167
168BOOLEAN newstruct_Op2(int op, leftv res, leftv a1, leftv a2)
169{
170  // interpreter: a1 is newstruct
171  blackbox *a=getBlackboxStuff(a1->Typ());
172  newstruct_desc nt=(newstruct_desc)a->data;
173  lists al=(lists)a1->Data();
174  switch(op)
175  {
176    case '.':
177    {
178      if (a2->name!=NULL)
179      {
180        BOOLEAN search_ring=FALSE;
181        newstruct_member nm=nt->member;
182        while ((nm!=NULL)&&(strcmp(nm->name,a2->name)!=0)) nm=nm->next;
183        if ((nm==NULL) && (strncmp(a2->name,"r_",2)==0))
184        {
185          nm=nt->member;
186          while ((nm!=NULL)&&(strcmp(nm->name,a2->name+2)!=0)) nm=nm->next;
187          if ((nm!=NULL)&&(RingDependend(nm->typ)))
188            search_ring=TRUE;
189          else
190            nm=NULL;
191        }
192        if (nm==NULL)
193        {
194          Werror("member %s nor found", a2->name);
195          return TRUE;
196        }
197        if (search_ring)
198        {
199          ring r;
200          res->rtyp=RING_CMD;
201          res->data=al->m[nm->pos-1].data;
202          r=(ring)res->data;
203          if (r==NULL) { res->data=(void *)currRing; r=currRing; }
204          if (r!=NULL) r->ref++;
205          else Werror("ring of this member is not set and no basering found");
206          return r==NULL;
207        }
208        else if (RingDependend(nm->typ))
209        {
210          if (al->m[nm->pos].data==NULL)
211          {
212            // NULL belongs to any ring
213            ring r=(ring)al->m[nm->pos-1].data;
214            if (r!=NULL)
215            {
216              r->ref--;
217              al->m[nm->pos-1].data=NULL;
218              al->m[nm->pos-1].rtyp=DEF_CMD;
219            }
220          }
221          else
222          {
223            //Print("checking ring at pos %d for dat at pos %d\n",nm->pos-1,nm->pos);
224            if ((al->m[nm->pos-1].data!=(void *)currRing)
225            &&(al->m[nm->pos-1].data!=(void*)0L))
226            {
227              Werror("different ring %lx(data) - %lx(basering)",
228                (long unsigned)(al->m[nm->pos-1].data),(long unsigned)currRing);
229              return TRUE;
230            }
231          }
232          if ((currRing!=NULL)&&(al->m[nm->pos-1].data==NULL))
233          {
234            // remember the ring, if not already set
235            al->m[nm->pos-1].data=(void *)currRing;
236            al->m[nm->pos-1].rtyp=RING_CMD;
237            currRing->ref++;
238          }
239        }
240        Subexpr r=(Subexpr)omAlloc0Bin(sSubexpr_bin);
241        r->start = nm->pos+1;
242        memcpy(res,a1,sizeof(sleftv));
243        memset(a1,0,sizeof(sleftv));
244        if (res->e==NULL) res->e=r;
245        else
246        {
247          Subexpr sh=res->e;
248          while (sh->next != NULL) sh=sh->next;
249          sh->next=r;
250        }
251        return FALSE;
252      }
253      else
254      {
255        WerrorS("name expected");
256        return TRUE;
257      }
258    }
259  }
260  return blackboxDefaultOp2(op,res,a1,a2);
261}
262
263// BOOLEAN opM(int op, leftv res, leftv args)
264BOOLEAN newstruct_OpM(int op, leftv res, leftv args)
265{
266  // interpreter: args->1. arg is newstruct
267  blackbox *a=getBlackboxStuff(args->Typ());
268  switch(op)
269  {
270    case STRING_CMD:
271    {
272      res->data=(void *)a->blackbox_String(a,args->Data());
273      res->rtyp=STRING_CMD;
274      return FALSE;
275    }
276    default:
277      return blackbox_default_OpM(op,res,args);
278      break;
279  }
280  return TRUE;
281}
282
283void newstruct_destroy(blackbox *b, void *d)
284{
285  if (d!=NULL)
286  {
287    lists n=(lists)d;
288    n->Clean();
289  }
290}
291
292void *newstruct_Init(blackbox *b)
293{
294  newstruct_desc n=(newstruct_desc)b->data;
295  lists l=(lists)omAlloc0Bin(slists_bin);
296  l->Init(n->size);
297  newstruct_member nm=n->member;
298  while (nm!=NULL)
299  {
300    l->m[nm->pos].rtyp=nm->typ;
301    l->m[nm->pos].data=idrecDataInit(nm->typ);
302    nm=nm->next;
303  }
304  return l;
305}
306
307BOOLEAN newstruct_Check(blackbox *b, void *d)
308{
309  newstruct_desc n=(newstruct_desc)b->data;
310  lists l=(lists)d;
311  newstruct_member nm=n->member;
312  while (nm!=NULL)
313  {
314    if ((l->m[nm->pos].rtyp!=nm->typ)
315    &&( nm->typ!=DEF_CMD))
316    {
317      Werror("type change in member %s (%s(%d) -> %s(%d))",nm->name,
318          Tok2Cmdname(nm->typ),nm->typ,
319          Tok2Cmdname(l->m[nm->pos].rtyp),l->m[nm->pos].rtyp);
320      return TRUE;
321    }
322    nm=nm->next;
323  }
324  return FALSE;
325}
326
327BOOLEAN newstruct_serialize(blackbox *b, void *d, si_link f)
328{
329  newstruct_desc dd=(newstruct_desc)b->data;
330  sleftv l;
331  memset(&l,0,sizeof(l));
332  l.rtyp=STRING_CMD;
333  l.data=(void*)getBlackboxName(dd->id);
334  f->m->Write(f, &l);
335  lists ll=(lists)d;
336  memset(&l,0,sizeof(l));
337  l.rtyp=LIST_CMD;
338  l.data=ll;
339  f->m->Write(f, &l);
340  return FALSE;
341}
342
343BOOLEAN newstruct_deserialize(blackbox **b, void **d, si_link f)
344{
345  // newstruct is serialiazed as a list,
346  // just read a list and take data,
347  // rtyp must be set correctly (to the blackbox id) by routine calling
348  // newstruct_deserialize
349  leftv l=f->m->Read(f);
350  //newstruct_desc n=(newstruct_desc)b->data;
351  //TODO: check compatibility of list l->data with description in n
352  *d=l->data;
353  return FALSE;
354}
355
356void newstruct_setup(const char *n, newstruct_desc d )
357{
358  blackbox *b=(blackbox*)omAlloc0(sizeof(blackbox));
359  // all undefined entries will be set to default in setBlackboxStuff
360  // the default Print is quite usefule,
361  // all other are simply error messages
362  b->blackbox_destroy=newstruct_destroy;
363  b->blackbox_String=newstruct_String;
364  //b->blackbox_Print=blackbox_default_Print;
365  b->blackbox_Init=newstruct_Init;
366  b->blackbox_Copy=newstruct_Copy;
367  b->blackbox_Assign=newstruct_Assign;
368  //b->blackbox_Op1=blackboxDefaultOp1;
369  b->blackbox_Op2=newstruct_Op2;
370  //b->blackbox_Op3=blackbox_default_Op3;
371  b->blackbox_OpM=newstruct_OpM;
372  b->blackbox_Check=newstruct_Check;
373  b->blackbox_serialize=newstruct_serialize;
374  b->blackbox_deserialize=newstruct_deserialize;
375  b->data=d;
376  b->properties=1; // list_like
377  int rt=setBlackboxStuff(b,n);
378  d->id=rt;
379  //Print("create type %d (%s)\n",rt,n);
380}
381
382static newstruct_desc scanNewstructFromString(const char *s, newstruct_desc res)
383{
384  char *ss=omStrDup(s);
385  char *p=ss;
386  char *start;
387  int t;
388  char c;
389  newstruct_member elem;
390
391  idhdl save_ring=currRingHdl;
392  currRingHdl=(idhdl)1; // fake ring detection
393  loop
394  {
395    // read type:
396    while (*p==' ') p++;
397    start=p;
398    while (isalpha(*p)) p++;
399    *p='\0';
400    IsCmd(start,t);
401    if (t==0)
402    {
403      Werror("unknown type `%s`",start);
404      omFree(ss);
405      omFree(res);
406      currRingHdl=save_ring;
407      return NULL;
408    }
409    if (RingDependend(t))
410      res->size++;    // one additional field for the ring (before the data)
411    //Print("found type %s at real-pos %d",start,res->size);
412    elem=(newstruct_member)omAlloc0(sizeof(*elem));
413    // read name:
414    p++;
415    while (*p==' ') p++;
416    start=p;
417    while (isalpha(*p)) p++;
418    c=*p;
419    *p='\0';
420    elem->typ=t;
421    elem->pos=res->size;
422    if (*start=='\0') /*empty name*/
423    {
424      WerrorS("empty name for element");
425      goto error_in_newstruct_def;
426    }
427    elem->name=omStrDup(start);
428    //Print(" name:%s\n",start);
429    elem->next=res->member;
430    res->member=elem;
431    res->size++;
432
433    // next ?
434    *p=c;
435    while (*p==' ') p++;
436    if (*p!=',')
437    {
438      if (*p!='\0')
439      {
440        Werror("unknown character in newstruct:>>%s<<",p);
441        goto error_in_newstruct_def;
442      }
443      break; // end-of-list
444    }
445    p++;
446  }
447  omFree(ss);
448  currRingHdl=save_ring;
449  //Print("new type with %d elements\n",res->size);
450  return res;
451error_in_newstruct_def:
452   omFree(elem);
453   omFree(ss);
454   omFree(res);
455   currRingHdl=save_ring;
456   return NULL;
457}
458newstruct_desc newstructFromString(const char *s)
459{
460  newstruct_desc res=(newstruct_desc)omAlloc0(sizeof(*res));
461  res->size=0;
462
463  return scanNewstructFromString(s,res);
464}
465newstruct_desc newstructChildFromString(const char *parent, const char *s)
466{
467  // find parent:
468  int parent_id=0;
469  blackboxIsCmd(parent,parent_id);
470  if (parent_id<MAX_TOK)
471  {
472    Werror(">>%s< not found",parent);
473    return NULL;
474  }
475  blackbox *parent_bb=getBlackboxStuff(parent_id);
476  // check for the correct type:
477  if (parent_bb->blackbox_destroy!=newstruct_destroy)
478  {
479    Werror(">>%s< is not a user defined type",parent);
480    return NULL;
481  }
482  // setup for scanNewstructFromString:
483  newstruct_desc res=(newstruct_desc)omAlloc0(sizeof(*res));
484  newstruct_desc parent_desc=(newstruct_desc)parent_bb->data;
485  res->size=parent_desc->size;
486  res->member=parent_desc->member;
487  res->parent=parent_desc;
488
489  return scanNewstructFromString(s,res);
490}
Note: See TracBrowser for help on using the repository browser.