#include "kernel/mod2.h" #include "Singular/ipid.h" #include "Singular/blackbox.h" #include "Singular/lists.h" #include "Singular/ipid.h" #include "Singular/ipshell.h" #include "Singular/ipconv.h" #include "Singular/newstruct.h" #include struct newstruct_member_s; typedef struct newstruct_member_s *newstruct_member; struct newstruct_member_s { newstruct_member next; char * name; int typ; int pos; }; struct newstruct_proc_s; typedef struct newstruct_proc_a *newstruct_proc; struct newstruct_proc_a { newstruct_proc next; int t; /*tok id */ int args; /* number of args */ procinfov p; }; struct newstruct_desc_s { newstruct_member member; newstruct_desc parent; newstruct_proc procs; int size; // number of mebers +1 int id; // the type id assigned to this bb }; int newstruct_desc_size() { return sizeof(newstruct_desc_s); } static inline int NeedShadowRing(int t) { return (RingDependend(t)|| (t==DEF_CMD) ||(t==LIST_CMD)); } char * newstruct_String(blackbox *b, void *d) { if (d==NULL) return omStrDup("oo"); else { newstruct_desc ad=(newstruct_desc)(b->data); newstruct_proc p=ad->procs; while((p!=NULL)&&(p->t!=STRING_CMD)) p=p->next; if (p!=NULL) { sleftv tmp; tmp.Init(); tmp.rtyp=ad->id; void * newstruct_Copy(blackbox*, void *); //forward declaration tmp.data=(void*)newstruct_Copy(b,d); idrec hh; hh.Init(); hh.id=Tok2Cmdname(p->t); hh.typ=PROC_CMD; hh.data.pinf=p->p; BOOLEAN sl=iiMake_proc(&hh,NULL,&tmp); if ((!sl)&& (iiRETURNEXPR.Typ() == STRING_CMD)) { char *res = (char*)iiRETURNEXPR.CopyD(); iiRETURNEXPR.Init(); return res; } iiRETURNEXPR.CleanUp(); iiRETURNEXPR.Init(); } lists l=(lists)d; newstruct_member a=ad->member; StringSetS(""); loop { StringAppendS(a->name); StringAppendS("="); if (((!RingDependend(a->typ)&&!RingDependend(l->m[a->pos].rtyp))) || ((rEqual((ring)l->m[a->pos-1].data,currRing)) && (currRing!=NULL))) { if (l->m[a->pos].rtyp==LIST_CMD) { StringAppendS(""); } else if (l->m[a->pos].rtyp==STRING_CMD) { StringAppendS((char*)l->m[a->pos].Data()); } else { char *tmp2=l->m[a->pos].String(); if ((strlen(tmp2)>80)||(strchr(tmp2,'\n')!=NULL)) { StringAppendS("<"); StringAppendS(Tok2Cmdname(l->m[a->pos].rtyp)); StringAppendS(">"); } else StringAppendS(tmp2); omFree(tmp2); } } else StringAppendS("??"); if (a->next==NULL) break; StringAppendS("\n"); if(errorreported) break; a=a->next; } return StringEndS(); } } lists lCopy_newstruct(lists L) { lists N=(lists)omAlloc0Bin(slists_bin); int n=L->nr; ring save_ring=currRing; N->Init(n+1); for(;n>=0;n--) { if (RingDependend(L->m[n].rtyp) ||((L->m[n].rtyp==LIST_CMD)&&lRingDependend((lists)L->m[n].data))) { assume((L->m[n-1].rtyp==RING_CMD) || (L->m[n-1].data==NULL)); if(L->m[n-1].data!=NULL) { if (L->m[n-1].data!=(void*)currRing) rChangeCurrRing((ring)(L->m[n-1].data)); N->m[n].Copy(&L->m[n]); } else { N->m[n].rtyp=L->m[n].rtyp; N->m[n].data=idrecDataInit(L->m[n].rtyp); } } else if(L->m[n].rtyp==LIST_CMD) { N->m[n].rtyp=L->m[n].rtyp; N->m[n].data=(void *)lCopy((lists)(L->m[n].data)); } else if(L->m[n].rtyp>MAX_TOK) { N->m[n].rtyp=L->m[n].rtyp; blackbox *b=getBlackboxStuff(N->m[n].rtyp); N->m[n].data=(void *)b->blackbox_Copy(b,L->m[n].data); } else N->m[n].Copy(&L->m[n]); } if (currRing!=save_ring) rChangeCurrRing(save_ring); return N; } void * newstruct_Copy(blackbox*, void *d) { lists n1=(lists)d; return (void*)lCopy_newstruct(n1); } // Used by newstruct_Assign for overloaded '=' BOOLEAN newstruct_Assign_user(int op, leftv l, leftv r) { blackbox *ll=getBlackboxStuff(op); assume(ll->data != NULL); newstruct_desc nt=(newstruct_desc)ll->data; newstruct_proc p=nt->procs; while( (p!=NULL) && ((p->t!='=')||(p->args!=1)) ) p=p->next; if (p!=NULL) { BOOLEAN sl; idrec hh; hh.Init(); hh.id=Tok2Cmdname(p->t); hh.typ=PROC_CMD; hh.data.pinf=p->p; sleftv tmp; tmp.Copy(r); sl = iiMake_proc(&hh, NULL, &tmp); if (!sl) { if (iiRETURNEXPR.Typ() == op) { memcpy(l,&iiRETURNEXPR,sizeof(sleftv)); iiRETURNEXPR.Init(); return FALSE; } iiRETURNEXPR.CleanUp(); iiRETURNEXPR.Init(); } } return TRUE; } void lClean_newstruct(lists l) { if (l->nr>=0) { int i; ring r=NULL; for(i=l->nr;i>=0;i--) { if ((i>0) && (l->m[i-1].rtyp==RING_CMD)) r=(ring)(l->m[i-1].data); else r=NULL; l->m[i].CleanUp(r); } omFreeSize((ADDRESS)l->m, (l->nr+1)*sizeof(sleftv)); l->nr=-1; } omFreeBin((ADDRESS)l,slists_bin); } static BOOLEAN newstruct_Assign_same(leftv l, leftv r) { assume(l->Typ() == r->Typ()); if (l->Data()!=NULL) { lists n1=(lists)l->Data(); lClean_newstruct(n1); } lists n2=(lists)r->Data(); n2=lCopy_newstruct(n2); r->CleanUp(); if (l->rtyp==IDHDL) { IDDATA((idhdl)l->data)=(char *)n2; } else { l->data=(void *)n2; } return FALSE; } BOOLEAN newstruct_Op1(int op, leftv res, leftv arg) { // interpreter: arg is newstruct blackbox *a=getBlackboxStuff(arg->Typ()); newstruct_desc nt=(newstruct_desc)a->data; newstruct_proc p=nt->procs; while((p!=NULL) &&( (p->t!=op) || (p->args!=1) )) p=p->next; if (p!=NULL) { idrec hh; hh.Init(); hh.id=Tok2Cmdname(p->t); hh.typ=PROC_CMD; hh.data.pinf=p->p; BOOLEAN sl=iiMake_proc(&hh,NULL,arg); if (sl) return TRUE; else { memcpy(res,&iiRETURNEXPR,sizeof(sleftv)); iiRETURNEXPR.Init(); return FALSE; } } return blackboxDefaultOp1(op,res,arg); } BOOLEAN newstruct_Assign(leftv l, leftv r) { assume(l->Typ() > MAX_TOK); if (l->Typ()==r->Typ()) { return newstruct_Assign_same(l,r); } if (r->Typ()>MAX_TOK) { blackbox *rr=getBlackboxStuff(r->Typ()); if (l->Typ()!=r->Typ()) { newstruct_desc rrn=(newstruct_desc)rr->data; if (rrn==NULL) // this is not a newstruct { Werror("custom type %s(%d) cannot be assigned to newstruct %s(%d)", Tok2Cmdname(r->Typ()), r->Typ(), Tok2Cmdname(l->Typ()), l->Typ()); return TRUE; } // try to find a parent newstruct: newstruct_desc rrp=rrn->parent; while ((rrp!=NULL)&&(rrp->id!=l->Typ())) rrp=rrp->parent; if (rrp!=NULL) { if (l->rtyp==IDHDL) { IDTYP((idhdl)l->data)=r->Typ(); } else { l->rtyp=r->Typ(); } } else // unrelated types - look for custom conversion { sleftv tmp; if (! newstruct_Op1(l->Typ(), &tmp, r)) return newstruct_Assign(l, &tmp); if(!newstruct_Assign_user(l->Typ(), &tmp, r)) return newstruct_Assign(l, &tmp); } } if (l->Typ()==r->Typ()) { return newstruct_Assign_same(l,r); } } else { sleftv tmp; if(!newstruct_Assign_user(l->Typ(), &tmp, r)) return newstruct_Assign(l, &tmp); } Werror("assign %s(%d) = %s(%d)", Tok2Cmdname(l->Typ()),l->Typ(),Tok2Cmdname(r->Typ()),r->Typ()); return TRUE; } BOOLEAN newstruct_Op2(int op, leftv res, leftv a1, leftv a2) { // interpreter: a1 or a2 is newstruct blackbox *a=getBlackboxStuff(a1->Typ()); newstruct_desc nt; lists al=(lists)a1->Data(); if (a!=NULL) { nt=(newstruct_desc)a->data; switch(op) { case '.': { if (a2->name!=NULL) { BOOLEAN search_ring=FALSE; newstruct_member nm=nt->member; while ((nm!=NULL)&&(strcmp(nm->name,a2->name)!=0)) nm=nm->next; if ((nm==NULL) && (strncmp(a2->name,"r_",2)==0)) { nm=nt->member; while ((nm!=NULL)&&(strcmp(nm->name,a2->name+2)!=0)) nm=nm->next; if ((nm!=NULL)&&(NeedShadowRing(nm->typ))) search_ring=TRUE; else nm=NULL; } if (nm==NULL) { Werror("member %s not found", a2->name); return TRUE; } if (search_ring) { ring r=(ring)al->m[nm->pos-1].data; res->rtyp=RING_CMD; if (r==NULL) { r=currRing; if (r==NULL) WerrorS("ring of this member is not set and no basering found"); } if (r!=NULL) res->data=rIncRefCnt(r); a1->CleanUp(); a2->CleanUp(); return r==NULL; } else if (RingDependend(nm->typ) || (al->m[nm->pos].RingDependend())) { if ((al->m[nm->pos].data==NULL)||(al->m[nm->pos-1].data==NULL)) { // NULL belongs to any ring ring r=(ring)al->m[nm->pos-1].data; if (r!=NULL) { rDecRefCnt(r); al->m[nm->pos-1].data=NULL; al->m[nm->pos-1].rtyp=DEF_CMD; } } else if (al->m[nm->pos-1].data!=currRing) { // object is not from currRing, so mark it for "write-only": al->m[nm->pos].flag|=Sy_bit(FLAG_OTHER_RING); //Print("checking ring at pos %d for dat at pos %d\n",nm->pos-1,nm->pos); } else { // object is from currRing, so mark it for "read-write": al->m[nm->pos].flag &= ~Sy_bit(FLAG_OTHER_RING); } al->m[nm->pos].flag|=Sy_bit(FLAG_RING); } else if ((nm->typ==DEF_CMD)||(nm->typ==LIST_CMD)) { if(al->m[nm->pos-1].data!=NULL) { ring old=(ring)al->m[nm->pos-1].data; rDecRefCnt(old); } al->m[nm->pos-1].data=(void*)currRing; if (currRing!=NULL) rIncRefCnt(currRing); } Subexpr r=(Subexpr)omAlloc0Bin(sSubexpr_bin); r->start = nm->pos+1; memcpy(res,a1,sizeof(sleftv)); a1->Init(); if (res->e==NULL) res->e=r; else { Subexpr sh=res->e; while (sh->next != NULL) sh=sh->next; sh->next=r; } //a1->CleanUp();// see Init() above a2->CleanUp(); return FALSE; } else { WerrorS("name expected"); return TRUE; } } } } else { a=getBlackboxStuff(a2->Typ()); nt=(newstruct_desc)a->data; al=(lists)a2->Data(); } newstruct_proc p=nt->procs; while((p!=NULL) && ( (p->t!=op) || (p->args!=2) )) p=p->next; if (p!=NULL) { sleftv tmp; tmp.Copy(a1); tmp.next=(leftv)omAlloc0(sizeof(sleftv)); tmp.next->Copy(a2); idrec hh; hh.Init(); hh.id=Tok2Cmdname(p->t); hh.typ=PROC_CMD; hh.data.pinf=p->p; BOOLEAN sl=iiMake_proc(&hh,NULL,&tmp); a1->CleanUp(); a2->CleanUp(); if (sl) return TRUE; else { memcpy(res,&iiRETURNEXPR,sizeof(sleftv)); iiRETURNEXPR.Init(); return FALSE; } } return blackboxDefaultOp2(op,res,a1,a2); } // BOOLEAN opM(int op, leftv res, leftv args) BOOLEAN newstruct_OpM(int op, leftv res, leftv args) { // interpreter: args->1. arg is newstruct blackbox *a=getBlackboxStuff(args->Typ()); newstruct_desc nt=(newstruct_desc)a->data; switch(op) { case STRING_CMD: { res->data=(void *)a->blackbox_String(a,args->Data()); res->rtyp=STRING_CMD; args->CleanUp(); return FALSE; } default: break; } newstruct_proc p=nt->procs; while((p!=NULL) &&( (p->t!=op) || (p->args!=4) )) p=p->next; if (p!=NULL) { idrec hh; hh.Init(); hh.id=Tok2Cmdname(p->t); hh.typ=PROC_CMD; hh.data.pinf=p->p; BOOLEAN sl=iiMake_proc(&hh,NULL,args); args->CleanUp(); if (sl) return TRUE; else { memcpy(res,&iiRETURNEXPR,sizeof(sleftv)); iiRETURNEXPR.Init(); return FALSE; } } return blackboxDefaultOpM(op,res,args); } void newstruct_destroy(blackbox */*b*/, void *d) { if (d!=NULL) { lists n=(lists)d; lClean_newstruct(n); } } void *newstruct_Init(blackbox *b) { newstruct_desc n=(newstruct_desc)b->data; lists l=(lists)omAlloc0Bin(slists_bin); l->Init(n->size); newstruct_member nm=n->member; while (nm!=NULL) { l->m[nm->pos].rtyp=nm->typ; if (NeedShadowRing(nm->typ)) { l->m[nm->pos-1].rtyp=RING_CMD; l->m[nm->pos-1].data=currRing; //idrecDataInit may create ringdep obj. if (currRing!=NULL) rIncRefCnt(currRing); } l->m[nm->pos].data=idrecDataInit(nm->typ); nm=nm->next; } return l; } BOOLEAN newstruct_CheckAssign(blackbox */*b*/, leftv L, leftv R) { int lt=L->Typ(); int rt=R->Typ(); if (iiTestConvert(rt,lt,dConvertTypes)==0) { const char *rt1=Tok2Cmdname(rt); const char *lt1=Tok2Cmdname(lt); if ((rt>0) && (lt>0) && ((strcmp(rt1,Tok2Cmdname(0))==0)||(strcmp(lt1,Tok2Cmdname(0))==0))) { Werror("can not assign %s(%d) to member of type %s(%d)", rt1,rt,lt1,lt); } else { Werror("can not assign %s to member of type %s",rt1,lt1); } return TRUE; } return FALSE; } /* check internal structure: * BOOLEAN newstruct_Check(blackbox *b, void *d) { newstruct_desc n=(newstruct_desc)b->data; lists l=(lists)d; newstruct_member nm=n->member; while (nm!=NULL) { if ((l->m[nm->pos].rtyp!=nm->typ) &&( nm->typ!=DEF_CMD)) { Werror("type change in member %s (%s(%d) -> %s(%d))",nm->name, Tok2Cmdname(nm->typ),nm->typ, Tok2Cmdname(l->m[nm->pos].rtyp),l->m[nm->pos].rtyp); return TRUE; } nm=nm->next; } return FALSE; } */ BOOLEAN newstruct_serialize(blackbox *b, void *d, si_link f) { newstruct_desc dd=(newstruct_desc)b->data; sleftv l; l.Init(); l.rtyp=STRING_CMD; l.data=(void*)getBlackboxName(dd->id); f->m->Write(f, &l); lists ll=(lists)d; int Ll=lSize(ll); l.rtyp=INT_CMD; l.data=(void*)(long)Ll; f->m->Write(f, &l); // set all entries corresponding to "real" members to 1 in rings char *rings=(char*)omAlloc0(Ll+1); newstruct_member elem=dd->member; while (elem!=NULL) { rings[elem->pos]='\1'; elem=elem->next; } int i; BOOLEAN ring_changed=FALSE; ring save_ring=currRing; for(i=0;i<=Ll;i++) { if (rings[i]=='\0') // ring entry for pos i+1 { if (ll->m[i].data!=NULL) { ring_changed=TRUE; f->m->SetRing(f,(ring)ll->m[i].data,TRUE); } } f->m->Write(f,&(ll->m[i])); } omFreeSize(rings,Ll+1); if (ring_changed && (save_ring!=NULL)) f->m->SetRing(f,save_ring,FALSE); return FALSE; } BOOLEAN newstruct_deserialize(blackbox **, void **d, si_link f) { // newstruct is serialized as analog to a list, // just read a list and take data, // rtyp must be set correctly (to the blackbox id) by routine calling // newstruct_deserialize leftv l=f->m->Read(f); // int: length of list int Ll=(int)(long)(l->data); omFreeBin(l,sleftv_bin); lists L=(lists)omAllocBin(slists_bin); L->Init(Ll+1); for(int i=0;i<=Ll;i++) { l=f->m->Read(f); memcpy(&(L->m[i]),l,sizeof(sleftv)); omFreeBin(l,sleftv_bin); } //newstruct_desc n=(newstruct_desc)b->data; //TODO: check compatibility of list l->data with description in n *d=L; return FALSE; } void newstruct_Print(blackbox *b,void *d) { newstruct_desc dd=(newstruct_desc)b->data; newstruct_proc p=dd->procs; while((p!=NULL)&&(p->t!=PRINT_CMD)) p=p->next; if (p!=NULL) { BOOLEAN sl; sleftv tmp; tmp.Init(); tmp.rtyp=dd->id; tmp.data=(void*)newstruct_Copy(b,d); idrec hh; hh.Init(); hh.id=Tok2Cmdname(p->t); hh.typ=PROC_CMD; hh.data.pinf=p->p; sl=iiMake_proc(&hh,NULL,&tmp); if (!sl) { if (iiRETURNEXPR.Typ()!=NONE) Warn("ignoring return value (%s)",Tok2Cmdname(iiRETURNEXPR.Typ())); iiRETURNEXPR.CleanUp(); } iiRETURNEXPR.Init(); } else blackbox_default_Print(b,d); } void newstruct_setup(const char *n, newstruct_desc d ) { blackbox *b=(blackbox*)omAlloc0(sizeof(blackbox)); // all undefined entries will be set to default in setBlackboxStuff // the default Print is quite useful, // all other are simply error messages b->blackbox_destroy=newstruct_destroy; b->blackbox_String=newstruct_String; b->blackbox_Print=newstruct_Print;//blackbox_default_Print; b->blackbox_Init=newstruct_Init; b->blackbox_Copy=newstruct_Copy; b->blackbox_Assign=newstruct_Assign; b->blackbox_Op1=newstruct_Op1; b->blackbox_Op2=newstruct_Op2; //b->blackbox_Op3=blackboxDefaultOp3; b->blackbox_OpM=newstruct_OpM; b->blackbox_CheckAssign=newstruct_CheckAssign; b->blackbox_serialize=newstruct_serialize; b->blackbox_deserialize=newstruct_deserialize; b->data=d; b->properties=1; // list_like int rt=setBlackboxStuff(b,n); d->id=rt; //Print("create type %d (%s)\n",rt,n); } static newstruct_desc scanNewstructFromString(const char *s, newstruct_desc res) { char *ss=omStrDup(s); char *p=ss; char *start; int t; char c; newstruct_member elem; idhdl save_ring=currRingHdl; currRingHdl=(idhdl)1; // fake ring detection loop { // read type: while ((*p!='\0') && (*p<=' ')) p++; start=p; while (isalnum(*p)) p++; *p='\0'; IsCmd(start,t); if (t==0) { Werror("unknown type `%s`",start); omFree(ss); omFree(res); currRingHdl=save_ring; return NULL; } if (t==QRING_CMD) t=RING_CMD; else if (NeedShadowRing(t)) res->size++; // one additional field for the ring (before the data) //Print("found type %s at real-pos %d",start,res->size); elem=(newstruct_member)omAlloc0(sizeof(*elem)); // read name: p++; while ((*p!='\0') && (*p<=' ')) p++; start=p; while (isalnum(*p)) p++; c=*p; *p='\0'; elem->typ=t; elem->pos=res->size; if ((*start=='\0') /*empty name*/||(isdigit(*start))) { WerrorS("illegal/empty name for element"); goto error_in_newstruct_def; } elem->name=omStrDup(start); //Print(" name:%s\n",start); elem->next=res->member; res->member=elem; res->size++; // next ? *p=c; while ((*p!='\0') && (*p<=' ')) p++; if (*p!=',') { if (*p!='\0') { Werror("unknown character in newstruct:>>%s<<",p); goto error_in_newstruct_def; } break; // end-of-list } p++; } omFree(ss); currRingHdl=save_ring; //Print("new type with %d elements\n",res->size); //newstructShow(res); return res; error_in_newstruct_def: omFree(elem); omFree(ss); omFree(res); currRingHdl=save_ring; return NULL; } newstruct_desc newstructFromString(const char *s) { newstruct_desc res=(newstruct_desc)omAlloc0(sizeof(*res)); res->size=0; return scanNewstructFromString(s,res); } newstruct_desc newstructChildFromString(const char *parent, const char *s) { // find parent: int parent_id=0; blackboxIsCmd(parent,parent_id); if (parent_id>%s< not found",parent); return NULL; } blackbox *parent_bb=getBlackboxStuff(parent_id); // check for the correct type: if (parent_bb->blackbox_destroy!=newstruct_destroy) { Werror(">>%s< is not a user defined type",parent); return NULL; } // setup for scanNewstructFromString: newstruct_desc res=(newstruct_desc)omAlloc0(sizeof(*res)); newstruct_desc parent_desc=(newstruct_desc)parent_bb->data; res->size=parent_desc->size; res->member=parent_desc->member; res->parent=parent_desc; return scanNewstructFromString(s,res); } void newstructShow(newstruct_desc d) { newstruct_member elem; Print("id: %d\n",d->id); elem=d->member; while (elem!=NULL) { Print(">>%s<< at pos %d, type %d (%s)\n",elem->name,elem->pos,elem->typ,Tok2Cmdname(elem->typ)); if (NeedShadowRing(elem->typ)) Print(">>r_%s<< at pos %d, shadow ring\n",elem->name,elem->pos-1); elem=elem->next; } newstruct_proc p=d->procs; while (p!=NULL) { Print("op:%d(%s) with %d args -> %s\n",p->t,iiTwoOps(p->t),p->args,p->p->procname); p=p->next; } } BOOLEAN newstruct_set_proc(const char *bbname,const char *func, int args,procinfov pr) { int id=0; blackboxIsCmd(bbname,id); if (id>%s<< is not a newstruct type",bbname); return TRUE; } blackbox *bb=getBlackboxStuff(id); newstruct_desc desc=(newstruct_desc)bb->data; newstruct_proc p=(newstruct_proc)omAlloc(sizeof(*p)); p->next=desc->procs; desc->procs=p; idhdl save_ring=currRingHdl; currRingHdl=(idhdl)1; // fake ring detection int tt; if(!(tt=IsCmd(func,p->t))) { int t; if((t=iiOpsTwoChar(func))!=0) { p->t=t; tt=CMD_2; /* ..,::, ==, <=, <>, >= !=i and +,-,*,/,%,.... */ if ((t==PLUSPLUS) ||(t==MINUSMINUS) ||(t=='=')) tt=CMD_1; /* ++,--,= */ else if (t=='(') /* proc call */ tt=CMD_M; else if (t=='-') /* unary and binary - */ tt=CMD_12; } else { desc->procs=p->next; omFreeSize(p,sizeof(*p)); Werror(">>%s<< is not a kernel command",func); currRingHdl = save_ring; return TRUE; } } switch(tt) { // type conversions: case BIGINTMAT_CMD: case MATRIX_CMD: case INTMAT_CMD: case RING_CMD: case RING_DECL: case ROOT_DECL: // operations: case CMD_1: if(args!=1) { Warn("args must be 1 for %s in %s",func,my_yylinebuf);args=1;} break; case CMD_2: if(args!=2) { Warn("args must be 2 in %s",my_yylinebuf);args=2;} break; case CMD_3: if(args!=3) { Warn("args must be 3 in %s",my_yylinebuf);args=3;} break; case CMD_12: if((args!=1)&&(args!=2)) { Werror("args must in 1 or 2 in %s",my_yylinebuf);} break; case CMD_13: if((args!=1)&&(args!=3)) { Werror("args must in 1 or 3 in %s",my_yylinebuf);} break; case CMD_23: if((args<2)||(args>3)) { Werror("args must in 2..3 in %s",my_yylinebuf);} break; case CMD_123: if((args<1)||(args>3)) { Werror("args must in 1..3 in %s",my_yylinebuf);} break; case RING_DECL_LIST: case ROOT_DECL_LIST: case CMD_M: break; default: Werror("unknown token type %d in %s",tt,my_yylinebuf); break; } currRingHdl = save_ring; if (errorreported) { desc->procs=p->next; omFreeSize(p,sizeof(*p)); return TRUE; } p->args=args; p->p=pr; pr->ref++; pr->is_static=0; return FALSE; }