source: git/Singular/links/ssiLink.cc @ 7e2307

spielwiese
Last change on this file since 7e2307 was 7e2307, checked in by Hans Schoenemann <hannes@…>, 8 years ago
fix: memeory leak: ssi ring construction: names
  • Property mode set to 100644
File size: 54.5 KB
Line 
1/****************************************
2 * Computer Algebra System SINGULAR     *
3 ****************************************/
4/***************************************************************
5 * File:    ssiLink.h
6 *  Purpose: declaration of sl_link routines for ssi
7 ***************************************************************/
8#define TRANSEXT_PRIVATES 1 /* allow access to transext internals */
9
10#include <kernel/mod2.h>
11
12#include <omalloc/omalloc.h>
13
14#include <misc/intvec.h>
15#include <misc/options.h>
16
17#include <reporter/si_signals.h>
18#include <reporter/s_buff.h>
19
20#include <coeffs/bigintmat.h>
21#include <coeffs/longrat.h>
22
23#include <polys/monomials/ring.h>
24#include <polys/monomials/p_polys.h>
25#include <polys/ext_fields/transext.h>
26#include <polys/simpleideals.h>
27#include <polys/matpol.h>
28
29#include <kernel/oswrapper/timer.h>
30#include <kernel/oswrapper/feread.h>
31#include <kernel/oswrapper/rlimit.h>
32
33#include <Singular/tok.h>
34#include <Singular/ipid.h>
35#include <Singular/ipshell.h>
36#include <Singular/subexpr.h>
37#include <Singular/links/silink.h>
38#include <Singular/cntrlc.h>
39#include <Singular/lists.h>
40#include <Singular/blackbox.h>
41#include <Singular/links/ssiLink.h>
42
43#ifdef HAVE_SIMPLEIPC
44#include <Singular/links/simpleipc.h>
45#endif
46
47#include <stdio.h>
48#include <fcntl.h>
49#include <errno.h>
50#include <unistd.h>
51#include <sys/types.h>
52#include <signal.h>
53#include <sys/types.h>          /* for portability */
54#include <sys/select.h>
55#include <sys/socket.h>
56#include <netinet/in.h>
57#include <ctype.h>   /*for isdigit*/
58#include <netdb.h>
59#include <sys/wait.h>
60#include <time.h>
61
62#define SSI_VERSION 10
63// 5->6: changed newstruct representation
64// 6->7: attributes
65// 7->8: qring
66// 8->9: module: added rank
67// 9->10: tokens in grammar.h/tok.h reorganized
68// 10->11: extended ring descr. for named coeffs (not in used until 4.1)
69
70link_list ssiToBeClosed=NULL;
71volatile BOOLEAN ssiToBeClosed_inactive=TRUE;
72
73// forward declarations:
74void ssiWritePoly_R(const ssiInfo *d, int typ, poly p, const ring r);
75void ssiWriteIdeal_R(const ssiInfo *d, int typ,const ideal I, const ring r);
76poly ssiReadPoly_R(const ssiInfo *D, const ring r);
77ideal ssiReadIdeal_R(const ssiInfo *d,const ring r);
78
79// the helper functions:
80BOOLEAN ssiSetCurrRing(const ring r) /* returned: not accepted */
81{
82  //  if (currRing!=NULL)
83  //  Print("need to change the ring, currRing:%s, switch to: ssiRing%d\n",IDID(currRingHdl),nr);
84  //  else
85  //  Print("no ring, switch to ssiRing%d\n",nr);
86  if (!rEqual(r,currRing,1))
87  {
88    char name[20];
89    int nr=0;
90    do
91    { sprintf(name,"ssiRing%d",nr); nr++; }
92    while(IDROOT->get(name, 0)!=NULL);
93    idhdl h=enterid(omStrDup(name),0,RING_CMD,&IDROOT,FALSE);
94    IDRING(h)=r;
95    r->ref++;
96    rSetHdl(h);
97    return FALSE;
98  }
99  else
100  {
101    rKill(r);
102    return TRUE;
103  }
104}
105// the implementation of the functions:
106void ssiWriteInt(const ssiInfo *d,const int i)
107{
108  fprintf(d->f_write,"%d ",i);
109  //if (d->f_debug!=NULL) fprintf(d->f_debug,"int: %d ",i);
110}
111
112void ssiWriteString(const ssiInfo *d,const char *s)
113{
114  fprintf(d->f_write,"%d %s ",(int)strlen(s),s);
115  //if (d->f_debug!=NULL) fprintf(d->f_debug,"stringi: %d \"%s\" ",strlen(s),s);
116}
117
118void ssiWriteBigInt(const ssiInfo *d, const number n)
119{
120 n_WriteFd(n,d->f_write,coeffs_BIGINT);
121}
122
123void ssiWriteNumber_CF(const ssiInfo *d, const number n, const coeffs cf)
124{
125  // syntax is as follows:
126  // case 1 Z/p:   3 <int>
127  // case 2 Q:     3 4 <int>
128  //        or     3 0 <mpz_t nominator> <mpz_t denominator>
129  //        or     3 1  dto.
130  //        or     3 3 <mpz_t nominator>
131  //        or     3 5 <mpz_t raw nom.> <mpz_t raw denom.>
132  //        or     3 6 <mpz_t raw nom.> <mpz_t raw denom.>
133  //        or     3 8 <mpz_t raw nom.>
134  if (getCoeffType(cf)==n_transExt)
135  {
136    fraction f=(fraction)n;
137    ssiWritePoly_R(d,POLY_CMD,NUM(f),cf->extRing);
138    ssiWritePoly_R(d,POLY_CMD,DEN(f),cf->extRing);
139  }
140  else if (getCoeffType(cf)==n_algExt)
141  {
142    ssiWritePoly_R(d,POLY_CMD,(poly)n,cf->extRing);
143  }
144  else if (cf->cfWriteFd!=NULL)
145  {
146    n_WriteFd(n,d->f_write,cf);
147  }
148  else WerrorS("coeff field not implemented");
149}
150
151void ssiWriteNumber(const ssiInfo *d, const number n)
152{
153  ssiWriteNumber_CF(d,n,d->r->cf);
154}
155
156void ssiWriteRing_R(ssiInfo *d,const ring r)
157{
158  /* 5 <ch> <N> <l1> <v1> ...<lN> <vN> <number of orderings> <ord1> <block0_1> <block1_1> .... <extRing> <Q-ideal> */
159  /* ch=-1: transext, coeff ring follows */
160  /* ch=-2: algext, coeff ring and minpoly follows */
161  /* ch=-3: cf name follows */
162  if (r!=NULL)
163  {
164    if (rField_is_Q(r) || rField_is_Zp(r))
165      fprintf(d->f_write,"%d %d ",n_GetChar(r->cf),r->N);
166    else if (rFieldType(r)==n_transExt)
167      fprintf(d->f_write,"-1 %d ",r->N);
168    else if (rFieldType(r)==n_algExt)
169      fprintf(d->f_write,"-2 %d ",r->N);
170    else /*dummy*/
171    {
172      fprintf(d->f_write,"-3 %d ",r->N);
173      ssiWriteString(d,nCoeffName(r->cf));
174    }
175
176    int i;
177    for(i=0;i<r->N;i++)
178    {
179      fprintf(d->f_write,"%d %s ",(int)strlen(r->names[i]),r->names[i]);
180    }
181    /* number of orderings:*/
182    i=0;
183    // remember dummy ring: everything 0:
184    if (r->order!=NULL) while (r->order[i]!=0) i++;
185    fprintf(d->f_write,"%d ",i);
186    /* each ordering block: */
187    i=0;
188    if (r->order!=NULL) while(r->order[i]!=0)
189    {
190      fprintf(d->f_write,"%d %d %d ",r->order[i],r->block0[i], r->block1[i]);
191      switch(r->order[i])
192      {
193        case ringorder_a:
194        case ringorder_wp:
195        case ringorder_Wp:
196        case ringorder_ws:
197        case ringorder_Ws:
198        case ringorder_aa:
199        {
200          int ii;
201          for(ii=r->block0[i];ii<=r->block1[i];ii++)
202            fprintf(d->f_write,"%d ",r->wvhdl[i][ii-r->block0[i]]);
203        }
204        break;
205
206        case ringorder_a64:
207        case ringorder_M:
208        case ringorder_L:
209        case ringorder_IS:
210          Werror("ring oder not implemented for ssi:%d",r->order[i]);
211          break;
212
213        default: break;
214      }
215      i++;
216    }
217    if ((rFieldType(r)==n_transExt)
218    || (rFieldType(r)==n_algExt))
219    {
220      ssiWriteRing_R(d,r->cf->extRing); /* includes alg.ext if rFieldType(r)==n_algExt */
221    }
222    /* Q-ideal :*/
223    if (r->qideal!=NULL)
224    {
225      ssiWriteIdeal_R(d,IDEAL_CMD,r->qideal,r);
226    }
227    else
228    {
229      fprintf(d->f_write,"0 "/*ideal with 0 entries */);
230    }
231  }
232  else /* dummy ring r==NULL*/
233  {
234    fprintf(d->f_write,"0 0 0 0 "/*,r->ch,r->N, blocks, q-ideal*/);
235  }
236}
237
238void ssiWriteRing(ssiInfo *d,const ring r)
239{
240  /* 5 <ch> <N> <l1> <v1> ...<lN> <vN> <number of orderings> <ord1> <block0_1> <block1_1> .... <extRing> <Q-ideal> */
241  /* ch=-1: transext, coeff ring follows */
242  /* ch=-2: algext, coeff ring and minpoly follows */
243  /* ch=-3: cf name follows */
244  if ((r==NULL)||(r->cf==NULL))
245  {
246    WerrorS("undefined ring");
247    return;
248  }
249  if (r==currRing) // see recursive calls for transExt/algExt
250  {
251    if (d->r!=NULL) rKill(d->r);
252    d->r=r;
253  }
254  if (r!=NULL)
255  {
256    /*d->*/r->ref++;
257  }
258  ssiWriteRing_R(d,r);
259}
260void ssiWritePoly_R(const ssiInfo *d, int typ, poly p, const ring r)
261{
262  fprintf(d->f_write,"%d ",pLength(p));//number of terms
263
264  while(p!=NULL)
265  {
266    ssiWriteNumber_CF(d,pGetCoeff(p),r->cf);
267    //nWrite(fich,pGetCoeff(p));
268    fprintf(d->f_write,"%ld ",p_GetComp(p,r));//component
269
270    for(int j=1;j<=rVar(r);j++)
271    {
272      fprintf(d->f_write,"%ld ",p_GetExp(p,j,r ));//x^j
273    }
274    pIter(p);
275  }
276}
277
278void ssiWritePoly(const ssiInfo *d, int typ, poly p)
279{
280  ssiWritePoly_R(d,typ,p,d->r);
281}
282
283void ssiWriteIdeal_R(const ssiInfo *d, int typ,const ideal I, const ring R)
284{
285   // syntax: 7 # of elements <poly 1> <poly2>.....
286   // syntax: 8 <rows> <cols> <poly 1> <poly2>.....
287   matrix M=(matrix)I;
288   int mn;
289   if (typ==MATRIX_CMD)
290   {
291     mn=MATROWS(M)*MATCOLS(M);
292     fprintf(d->f_write,"%d %d ", MATROWS(M),MATCOLS(M));
293   }
294   else
295   {
296     mn=IDELEMS(I);
297     fprintf(d->f_write,"%d ",IDELEMS(I));
298   }
299
300   int i;
301   int tt;
302   if (typ==MODUL_CMD) tt=VECTOR_CMD;
303   else                tt=POLY_CMD;
304
305   for(i=0;i<mn;i++)
306   {
307     ssiWritePoly_R(d,tt,I->m[i],R);
308   }
309}
310void ssiWriteIdeal(const ssiInfo *d, int typ,const ideal I)
311{
312  ssiWriteIdeal_R(d,typ,I,d->r);
313}
314
315void ssiWriteCommand(si_link l, command D)
316{
317  ssiInfo *d=(ssiInfo*)l->data;
318  // syntax: <num ops> <operation> <op1> <op2> ....
319  fprintf(d->f_write,"%d %d ",D->argc,D->op);
320  if (D->argc >0) ssiWrite(l, &(D->arg1));
321  if (D->argc < 4)
322  {
323    if (D->argc >1) ssiWrite(l, &(D->arg2));
324    if (D->argc >2) ssiWrite(l, &(D->arg3));
325  }
326}
327
328void ssiWriteProc(const ssiInfo *d,procinfov p)
329{
330  if (p->data.s.body==NULL)
331    iiGetLibProcBuffer(p);
332  if (p->data.s.body!=NULL)
333    ssiWriteString(d,p->data.s.body);
334  else
335    ssiWriteString(d,"");
336}
337
338void ssiWriteList(si_link l,lists dd)
339{
340  ssiInfo *d=(ssiInfo*)l->data;
341  int Ll=dd->nr;
342  fprintf(d->f_write,"%d ",Ll+1);
343  int i;
344  for(i=0;i<=Ll;i++)
345  {
346    ssiWrite(l,&(dd->m[i]));
347  }
348}
349void ssiWriteIntvec(const ssiInfo *d,intvec * v)
350{
351  fprintf(d->f_write,"%d ",v->length());
352  int i;
353  for(i=0;i<v->length();i++)
354  {
355    fprintf(d->f_write,"%d ",(*v)[i]);
356  }
357}
358void ssiWriteIntmat(const ssiInfo *d,intvec * v)
359{
360  fprintf(d->f_write,"%d %d ",v->rows(),v->cols());
361  int i;
362  for(i=0;i<v->length();i++)
363  {
364    fprintf(d->f_write,"%d ",(*v)[i]);
365  }
366}
367
368void ssiWriteBigintmat(const ssiInfo *d,bigintmat * v)
369{
370  fprintf(d->f_write,"%d %d ",v->rows(),v->cols());
371  int i;
372  for(i=0;i<v->length();i++)
373  {
374    ssiWriteBigInt(d,(*v)[i]);
375  }
376}
377
378char *ssiReadString(const ssiInfo *d)
379{
380  char *buf;
381  int l;
382  l=s_readint(d->f_read);
383  buf=(char*)omAlloc0(l+1);
384  int throwaway =s_getc(d->f_read); /* skip ' '*/
385  throwaway=s_readbytes(buf,l,d->f_read);
386  //if (throwaway!=l) printf("want %d, got %d bytes\n",l,throwaway);
387  buf[l]='\0';
388  return buf;
389}
390
391int ssiReadInt(s_buff fich)
392{
393  return s_readint(fich);
394}
395
396number ssiReadNumber_CF(const ssiInfo *d, const coeffs cf)
397{
398  if (cf->cfReadFd!=NULL)
399  {
400     return n_ReadFd(d->f_read,cf);
401  }
402  else if (getCoeffType(cf) == n_transExt)
403  {
404    // poly poly
405    fraction f=(fraction)n_Init(1,cf);
406    p_Delete(&NUM(f),cf->extRing);
407    NUM(f)=ssiReadPoly_R(d,cf->extRing);
408    DEN(f)=ssiReadPoly_R(d,cf->extRing);
409    return (number)f;
410  }
411  else if (getCoeffType(cf) == n_algExt)
412  {
413    // poly
414    return (number)ssiReadPoly_R(d,cf->extRing);
415  }
416  else WerrorS("coeffs not implemented in ssiReadNumber");
417  return NULL;
418}
419
420number ssiReadBigInt(const ssiInfo *d)
421{
422  number n=ssiReadNumber_CF(d,coeffs_BIGINT);
423  if ((SR_HDL(n) & SR_INT)==0)
424  {
425    if (n->s!=3) Werror("invalid sub type in bigint:%d",n->s);
426  }
427  return n;
428}
429
430number ssiReadNumber(const ssiInfo *d)
431{
432  return ssiReadNumber_CF(d,d->r->cf);
433}
434
435ring ssiReadRing(const ssiInfo *d)
436{
437/* syntax is <ch> <N> <l1> <v1> ...<lN> <vN> <number of orderings> <ord1> <block0_1> <block1_1> .... <Q-ideal> */
438  int ch, N,i;
439  char **names;
440  ch=s_readint(d->f_read);
441  N=s_readint(d->f_read);
442  coeffs cf=NULL;
443  if (ch==-3)
444  {
445    char *cf_name=ssiReadString(d);
446    cf=nFindCoeffByName(cf_name);
447    if (cf==NULL)
448    {
449      Werror("cannot find cf:%s",cf_name);
450      omFree(cf_name);
451      return NULL;
452    }
453  }
454  if (N!=0)
455  {
456    names=(char**)omAlloc(N*sizeof(char*));
457    for(i=0;i<N;i++)
458    {
459      names[i]=ssiReadString(d);
460    }
461  }
462  // read the orderings:
463  int num_ord; // number of orderings
464  num_ord=s_readint(d->f_read);
465  int *ord=(int *)omAlloc0((num_ord+1)*sizeof(int));
466  int *block0=(int *)omAlloc0((num_ord+1)*sizeof(int));
467  int *block1=(int *)omAlloc0((num_ord+1)*sizeof(int));
468  int **wvhdl=(int**)omAlloc0((num_ord+1)*sizeof(int*));
469  for(i=0;i<num_ord;i++)
470  {
471    ord[i]=s_readint(d->f_read);
472    block0[i]=s_readint(d->f_read);
473    block1[i]=s_readint(d->f_read);
474    switch(ord[i])
475    {
476      case ringorder_a:
477      case ringorder_wp:
478      case ringorder_Wp:
479      case ringorder_ws:
480      case ringorder_Ws:
481      case ringorder_aa:
482      {
483        wvhdl[i]=(int*)omAlloc((block1[i]-block0[i]+1)*sizeof(int));
484        int ii;
485        for(ii=block0[i];ii<=block1[i];ii++)
486          wvhdl[i][ii-block0[i]]=s_readint(d->f_read);
487      }
488      break;
489
490      case ringorder_a64:
491      case ringorder_M:
492      case ringorder_L:
493      case ringorder_IS:
494        Werror("ring oder not implemented for ssi:%d",ord[i]);
495        break;
496
497      default: break;
498    }
499  }
500  if (N==0)
501  {
502    omFree(ord);
503    omFree(block0);
504    omFree(block1);
505    omFree(wvhdl);
506    return NULL;
507  }
508  else
509  {
510    ring r=NULL;
511    if (ch>=0) /* Q, Z/p */
512      r=rDefault(ch,N,names,num_ord,ord,block0,block1,wvhdl);
513    else if (ch==-1) /* trans ext. */
514    {
515      TransExtInfo T;
516      T.r=ssiReadRing(d);
517      if (T.r==NULL) return NULL;
518      cf=nInitChar(n_transExt,&T);
519      r=rDefault(cf,N,names,num_ord,ord,block0,block1,wvhdl);
520    }
521    else if (ch==-2) /* alg ext. */
522    {
523      TransExtInfo T;
524      T.r=ssiReadRing(d); /* includes qideal */
525      if (T.r==NULL) return NULL;
526      cf=nInitChar(n_algExt,&T);
527      r=rDefault(cf,N,names,num_ord,ord,block0,block1,wvhdl);
528    }
529    else if (ch==-3)
530    {
531      r=rDefault(cf,N,names,num_ord,ord,block0,block1,wvhdl);
532    }
533    else
534    {
535      Werror("ssi: read unknown coeffs type (%d)",ch);
536      for(i=0;i<N;i++)
537      {
538        omFree(names[i]);
539      }
540      omFreeSize(names,N*sizeof(char*));
541      return NULL;
542    }
543    ideal q=ssiReadIdeal_R(d,r);
544    if (IDELEMS(q)==0) omFreeBin(q,sip_sideal_bin);
545    else r->qideal=q;
546    for(i=0;i<N;i++)
547    {
548      omFree(names[i]);
549    }
550    omFreeSize(names,N*sizeof(char*));
551    return r;
552  }
553}
554
555poly ssiReadPoly_R(const ssiInfo *D, const ring r)
556{
557// < # of terms> < term1> < .....
558  int n,i,l;
559  n=ssiReadInt(D->f_read); // # of terms
560  //Print("poly: terms:%d\n",n);
561  poly p;
562  poly ret=NULL;
563  poly prev=NULL;
564  for(l=0;l<n;l++) // read n terms
565  {
566// coef,comp.exp1,..exp N
567    p=p_Init(r);
568    pSetCoeff0(p,ssiReadNumber_CF(D,r->cf));
569    int d;
570    d=s_readint(D->f_read);
571    p_SetComp(p,d,r);
572    for(i=1;i<=rVar(r);i++)
573    {
574      d=s_readint(D->f_read);
575      p_SetExp(p,i,d,r);
576    }
577    p_Setm(p,r);
578    p_Test(p,r);
579    if (ret==NULL) ret=p;
580    else           pNext(prev)=p;
581    prev=p;
582 }
583 return ret;
584}
585
586poly ssiReadPoly(const ssiInfo *D)
587{
588// < # of terms> < term1> < .....
589  return ssiReadPoly_R(D,D->r);
590}
591
592ideal ssiReadIdeal_R(const ssiInfo *d,const ring r)
593{
594  int n,i;
595  ideal I;
596  n=s_readint(d->f_read);
597  I=idInit(n,1);
598  for(i=0;i<IDELEMS(I);i++) // read n terms
599  {
600    I->m [i]=ssiReadPoly_R(d,r);
601  }
602  return I;
603}
604
605ideal ssiReadIdeal(const ssiInfo *d)
606{
607  return ssiReadIdeal_R(d,d->r);
608}
609
610matrix ssiReadMatrix(const ssiInfo *d)
611{
612  int n,m;
613  m=s_readint(d->f_read);
614  n=s_readint(d->f_read);
615  matrix M=mpNew(m,n);
616  poly p;
617  for(int i=1;i<=MATROWS(M);i++)
618    for(int j=1;j<=MATCOLS(M);j++)
619    {
620      p=ssiReadPoly(d);
621      MATELEM(M,i,j)=p;
622    }
623  return M;
624}
625
626command ssiReadCommand(si_link l)
627{
628  ssiInfo *d=(ssiInfo*)l->data;
629  // syntax: <num ops> <operation> <op1> <op2> ....
630  command D=(command)omAlloc0(sizeof(*D));
631  int argc,op;
632  argc=s_readint(d->f_read);
633  op=s_readint(d->f_read);
634  D->argc=argc; D->op=op;
635  leftv v;
636  if (argc >0)
637  {
638    v=ssiRead1(l);
639    memcpy(&(D->arg1),v,sizeof(*v));
640    omFreeBin(v,sleftv_bin);
641  }
642  if (argc <4)
643  {
644    if (D->argc >1)
645    {
646      v=ssiRead1(l);
647      memcpy(&(D->arg2),v,sizeof(*v));
648      omFreeBin(v,sleftv_bin);
649    }
650    if (D->argc >2)
651    {
652      v=ssiRead1(l);
653      memcpy(&(D->arg3),v,sizeof(*v));
654      omFreeBin(v,sleftv_bin);
655    }
656  }
657  else
658  {
659    leftv prev=&(D->arg1);
660    argc--;
661    while(argc >0)
662    {
663      v=ssiRead1(l);
664      prev->next=v;
665      prev=v;
666      argc--;
667    }
668  }
669  return D;
670}
671
672procinfov ssiReadProc(const ssiInfo *d)
673{
674  char *s=ssiReadString(d);
675  procinfov p=(procinfov)omAlloc0Bin(procinfo_bin);
676  p->language=LANG_SINGULAR;
677  p->libname=omStrDup("");
678  p->procname=omStrDup("");
679  p->data.s.body=s;
680  return p;
681}
682lists ssiReadList(si_link l)
683{
684  ssiInfo *d=(ssiInfo*)l->data;
685  int nr;
686  nr=s_readint(d->f_read);
687  lists L=(lists)omAlloc0Bin(slists_bin);
688  L->Init(nr);
689
690  int i;
691  leftv v;
692  for(i=0;i<=L->nr;i++)
693  {
694    v=ssiRead1(l);
695    memcpy(&(L->m[i]),v,sizeof(*v));
696    omFreeBin(v,sleftv_bin);
697  }
698  return L;
699}
700intvec* ssiReadIntvec(const ssiInfo *d)
701{
702  int nr;
703  nr=s_readint(d->f_read);
704  intvec *v=new intvec(nr);
705  for(int i=0;i<nr;i++)
706  {
707    (*v)[i]=s_readint(d->f_read);
708  }
709  return v;
710}
711intvec* ssiReadIntmat(const ssiInfo *d)
712{
713  int r,c;
714  r=s_readint(d->f_read);
715  c=s_readint(d->f_read);
716  intvec *v=new intvec(r,c,0);
717  for(int i=0;i<r*c;i++)
718  {
719    (*v)[i]=s_readint(d->f_read);
720  }
721  return v;
722}
723bigintmat* ssiReadBigintmat(const ssiInfo *d)
724{
725  int r,c;
726  r=s_readint(d->f_read);
727  c=s_readint(d->f_read);
728  bigintmat *v=new bigintmat(r,c,coeffs_BIGINT);
729  for(int i=0;i<r*c;i++)
730  {
731    (*v)[i]=ssiReadBigInt(d);
732  }
733  return v;
734}
735
736void ssiReadBlackbox(leftv res, si_link l)
737{
738  ssiInfo *d=(ssiInfo*)l->data;
739  int throwaway=s_readint(d->f_read);
740  char *name=ssiReadString(d);
741  int tok;
742  blackboxIsCmd(name,tok);
743  if (tok>MAX_TOK)
744  {
745    blackbox *b=getBlackboxStuff(tok);
746    res->rtyp=tok;
747    b->blackbox_deserialize(&b,&(res->data),l);
748  }
749  else
750  {
751    Werror("blackbox %s not found",name);
752  }
753  omFree(name);
754}
755
756void ssiReadAttrib(leftv res, si_link l)
757{
758  ssiInfo *d=(ssiInfo*)l->data;
759  BITSET fl=(BITSET)s_readint(d->f_read);
760  int nr_of_attr=s_readint(d->f_read);
761  if (nr_of_attr>0)
762  {
763    for(int i=1;i<nr_of_attr;i++)
764    {
765    }
766  }
767  leftv tmp=ssiRead1(l);
768  memcpy(res,tmp,sizeof(sleftv));
769  memset(tmp,0,sizeof(sleftv));
770  omFreeBin(tmp,sleftv_bin);
771  if (nr_of_attr>0)
772  {
773  }
774  res->flag=fl;
775}
776//**************************************************************************/
777
778BOOLEAN ssiOpen(si_link l, short flag, leftv u)
779{
780  if (l!=NULL)
781  {
782    const char *mode;
783    ssiInfo *d=(ssiInfo*)omAlloc0(sizeof(ssiInfo));
784    if (flag & SI_LINK_OPEN)
785    {
786      if (l->mode[0] != '\0' && (strcmp(l->mode, "r") == 0))
787        flag = SI_LINK_READ;
788      else flag = SI_LINK_WRITE;
789    }
790
791    if (flag == SI_LINK_READ) mode = "r";
792    else if (strcmp(l->mode, "w") == 0) mode = "w";
793    else if (strcmp(l->mode, "fork") == 0) mode = "fork";
794    else if (strcmp(l->mode, "tcp") == 0) mode = "tcp";
795    else if (strcmp(l->mode, "connect") == 0) mode = "connect";
796    else mode = "a";
797
798
799    SI_LINK_SET_OPEN_P(l, flag);
800    if(l->data!=NULL) omFreeSize(l->data,sizeof(ssiInfo));
801    l->data=d;
802    omFree(l->mode);
803    l->mode = omStrDup(mode);
804
805    if (l->name[0] == '\0')
806    {
807      if (strcmp(mode,"fork")==0)
808      {
809        link_list n=(link_list)omAlloc(sizeof(link_struct));
810        n->u=u;
811        n->l=l;
812        n->next=(void *)ssiToBeClosed;
813        ssiToBeClosed=n;
814
815        int pc[2];
816        int cp[2];
817        pipe(pc);
818        pipe(cp);
819        pid_t pid = fork();
820        if (pid == -1 && errno == EAGAIN)   // RLIMIT_NPROC too low?
821        {
822          raise_rlimit_nproc();
823          pid = fork();
824        }
825        if (pid == -1)
826        {
827          WerrorS("could not fork");
828        }
829        if (pid==0) /*fork: child*/
830        {
831          /* block SIGINT */
832          sigset_t sigint;
833          sigemptyset(&sigint);
834          sigaddset(&sigint, SIGINT);
835          sigprocmask(SIG_BLOCK, &sigint, NULL);
836
837          link_list hh=(link_list)ssiToBeClosed->next;
838          /* we know: l is the first entry in ssiToBeClosed-list */
839          while(hh!=NULL)
840          {
841            SI_LINK_SET_CLOSE_P(hh->l);
842            ssiInfo *dd=(ssiInfo*)hh->l->data;
843            s_close(dd->f_read);
844            fclose(dd->f_write);
845            if (dd->r!=NULL) rKill(dd->r);
846            omFreeSize((ADDRESS)dd,(sizeof *dd));
847            hh->l->data=NULL;
848            link_list nn=(link_list)hh->next;
849            omFree(hh);
850            hh=nn;
851          }
852          ssiToBeClosed->next=NULL;
853#ifdef HAVE_SIMPLEIPC
854          memset(sem_acquired, 0, SIPC_MAX_SEMAPHORES*sizeof(sem_acquired[0]));
855#endif   // HAVE_SIMPLEIPC
856          si_close(pc[1]); si_close(cp[0]);
857          d->f_write=fdopen(cp[1],"w");
858          d->f_read=s_open(pc[0]);
859          d->fd_read=pc[0];
860          d->fd_write=cp[1];
861          //d->r=currRing;
862          //if (d->r!=NULL) d->r->ref++;
863          l->data=d;
864          omFree(l->mode);
865          l->mode = omStrDup(mode);
866          singular_in_batchmode=TRUE;
867          SI_LINK_SET_RW_OPEN_P(l);
868          //myynest=0;
869          fe_fgets_stdin=fe_fgets_dummy;
870          if ((u!=NULL)&&(u->rtyp==IDHDL))
871          {
872            idhdl h=(idhdl)u->data;
873            h->lev=0;
874          }
875          loop
876          {
877            if (!SI_LINK_OPEN_P(l)) m2_end(0);
878            if(d->f_read->is_eof) m2_end(0);
879            leftv h=ssiRead1(l); /*contains an exit.... */
880            if (feErrors != NULL && *feErrors != '\0')
881            {
882              // handle errors:
883              PrintS(feErrors); /* currently quite simple */
884              *feErrors = '\0';
885            }
886            ssiWrite(l,h);
887            h->CleanUp();
888            omFreeBin(h, sleftv_bin);
889          }
890          /* never reached*/
891        }
892        else if (pid>0) /*fork: parent*/
893        {
894          d->pid=pid;
895          si_close(pc[0]); si_close(cp[1]);
896          d->f_write=fdopen(pc[1],"w");
897          d->f_read=s_open(cp[0]);
898          d->fd_read=cp[0];
899          d->fd_write=pc[1];
900          SI_LINK_SET_RW_OPEN_P(l);
901          d->send_quit_at_exit=1;
902          //d->r=currRing;
903          //if (d->r!=NULL) d->r->ref++;
904        }
905        else
906        {
907          Werror("fork failed (%d)",errno);
908          l->data=NULL;
909          omFree(d);
910          return TRUE;
911        }
912      }
913      // ---------------------------------------------------------------------
914      else if (strcmp(mode,"tcp")==0)
915      {
916        int sockfd, newsockfd, portno, clilen;
917        struct sockaddr_in serv_addr, cli_addr;
918        sockfd = socket(AF_INET, SOCK_STREAM, 0);
919        if(sockfd < 0)
920        {
921          WerrorS("ERROR opening socket");
922          l->data=NULL;
923          omFree(d);
924          return TRUE;
925        }
926        memset((char *) &serv_addr,0, sizeof(serv_addr));
927        portno = 1025;
928        serv_addr.sin_family = AF_INET;
929        serv_addr.sin_addr.s_addr = INADDR_ANY;
930        do
931        {
932          portno++;
933          serv_addr.sin_port = htons(portno);
934          if(portno > 50000)
935          {
936            WerrorS("ERROR on binding (no free port available?)");
937            l->data=NULL;
938            omFree(d);
939            return TRUE;
940          }
941        }
942        while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0);
943        Print("waiting on port %d\n", portno);mflush();
944        listen(sockfd,1);
945        newsockfd = si_accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
946        if(newsockfd < 0)
947        {
948          WerrorS("ERROR on accept");
949          l->data=NULL;
950          omFree(d);
951          return TRUE;
952        }
953        PrintS("client accepted\n");
954        d->fd_read = newsockfd;
955        d->fd_write = newsockfd;
956        d->f_read = s_open(newsockfd);
957        d->f_write = fdopen(newsockfd, "w");
958        SI_LINK_SET_RW_OPEN_P(l);
959        si_close(sockfd);
960      }
961      // no ssi-Link on stdin or stdout
962      else
963      {
964        Werror("invalid mode >>%s<< for ssi",mode);
965        l->data=NULL;
966        omFree(d);
967        return TRUE;
968      }
969    }
970    // =========================================================================
971    else /*l->name=NULL*/
972    {
973      // tcp mode
974      if(strcmp(mode,"tcp")==0)
975      {
976        int sockfd, newsockfd, portno, clilen;
977        struct sockaddr_in serv_addr, cli_addr;
978        sockfd = socket(AF_INET, SOCK_STREAM, 0);
979        if(sockfd < 0)
980        {
981          WerrorS("ERROR opening socket");
982          l->data=NULL;
983          omFree(d);
984          return TRUE;
985        }
986        memset((char *) &serv_addr,0, sizeof(serv_addr));
987        portno = 1025;
988        serv_addr.sin_family = AF_INET;
989        serv_addr.sin_addr.s_addr = INADDR_ANY;
990        do
991        {
992          portno++;
993          serv_addr.sin_port = htons(portno);
994          if(portno > 50000)
995          {
996            WerrorS("ERROR on binding (no free port available?)");
997            l->data=NULL;
998            return TRUE;
999          }
1000        }
1001        while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0);
1002        //Print("waiting on port %d\n", portno);mflush();
1003        listen(sockfd,1);
1004        char* cli_host = (char*)omAlloc(256);
1005        char* path = (char*)omAlloc(1024);
1006        int r = si_sscanf(l->name,"%255[^:]:%s",cli_host,path);
1007        if(r == 0)
1008        {
1009          WerrorS("ERROR: no host specified");
1010          l->data=NULL;
1011          omFree(d);
1012          omFree(path);
1013          omFree(cli_host);
1014          return TRUE;
1015        }
1016        else if(r == 1)
1017        {
1018          WarnS("program not specified, using /usr/local/bin/Singular");
1019          Warn("in line >>%s<<",my_yylinebuf);
1020          strcpy(path,"/usr/local/bin/Singular");
1021        }
1022        char* ssh_command = (char*)omAlloc(256);
1023        char* ser_host = (char*)omAlloc(64);
1024        gethostname(ser_host,64);
1025        sprintf(ssh_command,"ssh %s %s -q --batch --link=ssi --MPhost=%s --MPport=%d &",cli_host,path,ser_host,portno);
1026        //Print("client on %s started:%s\n",cli_host,path);
1027        omFree(path);
1028        omFree(cli_host);
1029        if (TEST_OPT_PROT) { Print("running >>%s<<\n",ssh_command); }
1030        system(ssh_command);
1031        omFree(ssh_command);
1032        omFree(ser_host);
1033        clilen = sizeof(cli_addr);
1034        newsockfd = si_accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
1035        if(newsockfd < 0)
1036        {
1037          WerrorS("ERROR on accept");
1038          l->data=NULL;
1039          omFree(d);
1040          return TRUE;
1041        }
1042        //PrintS("client accepted\n");
1043        d->fd_read = newsockfd;
1044        d->fd_write = newsockfd;
1045        d->f_read = s_open(newsockfd);
1046        d->f_write = fdopen(newsockfd, "w");
1047        si_close(sockfd);
1048        SI_LINK_SET_RW_OPEN_P(l);
1049        d->send_quit_at_exit=1;
1050        link_list newlink=(link_list)omAlloc(sizeof(link_struct));
1051        newlink->u=u;
1052        newlink->l=l;
1053        newlink->next=(void *)ssiToBeClosed;
1054        ssiToBeClosed=newlink;
1055        fprintf(d->f_write,"98 %d %d %u %u\n",SSI_VERSION,MAX_TOK,si_opt_1,si_opt_2);
1056      }
1057      // ----------------------------------------------------------------------
1058      else if(strcmp(mode,"connect")==0)
1059      {
1060        char* host = (char*)omAlloc(256);
1061        int sockfd, portno;
1062        struct sockaddr_in serv_addr;
1063        struct hostent *server;
1064
1065        si_sscanf(l->name,"%255[^:]:%d",host,&portno);
1066        //Print("connect to host %s, port %d\n",host,portno);mflush();
1067        if (portno!=0)
1068        {
1069          sockfd = socket(AF_INET, SOCK_STREAM, 0);
1070          if (sockfd < 0) { WerrorS("ERROR opening socket"); return TRUE; }
1071          server = gethostbyname(host);
1072          if (server == NULL) {  WerrorS("ERROR, no such host");  return TRUE; }
1073          memset((char *) &serv_addr, 0, sizeof(serv_addr));
1074          serv_addr.sin_family = AF_INET;
1075          memcpy((char *)&serv_addr.sin_addr.s_addr,
1076                (char *)server->h_addr,
1077                server->h_length);
1078          serv_addr.sin_port = htons(portno);
1079          if (si_connect(sockfd,(sockaddr*)&serv_addr,sizeof(serv_addr)) < 0)
1080          { Werror("ERROR connecting(errno=%d)",errno); return TRUE; }
1081          //PrintS("connected\n");mflush();
1082          d->f_read=s_open(sockfd);
1083          d->fd_read=sockfd;
1084          d->f_write=fdopen(sockfd,"w");
1085          d->fd_write=sockfd;
1086          SI_LINK_SET_RW_OPEN_P(l);
1087          omFree(host);
1088        }
1089        else
1090        {
1091          l->data=NULL;
1092          omFree(d);
1093          return TRUE;
1094        }
1095      }
1096      // ======================================================================
1097      else
1098      {
1099        // normal link to a file
1100        FILE *outfile;
1101        char *filename=l->name;
1102
1103        if(filename[0]=='>')
1104        {
1105          if (filename[1]=='>')
1106          {
1107            filename+=2;
1108            mode = "a";
1109          }
1110          else
1111          {
1112            filename++;
1113            mode="w";
1114          }
1115        }
1116        outfile=myfopen(filename,mode);
1117        if (outfile!=NULL)
1118        {
1119          if (strcmp(l->mode,"r")==0)
1120          {
1121            fclose(outfile);
1122            d->f_read=s_open_by_name(filename);
1123          }
1124          else
1125          {
1126            d->f_write = outfile;
1127            fprintf(d->f_write,"98 %d %d %u %u\n",SSI_VERSION,MAX_TOK,si_opt_1,si_opt_2);
1128          }
1129        }
1130        else
1131        {
1132          omFree(d);
1133          l->data=NULL;
1134          return TRUE;
1135        }
1136      }
1137    }
1138  }
1139
1140  return FALSE;
1141}
1142
1143//**************************************************************************/
1144BOOLEAN ssiPrepClose(si_link l)
1145{
1146  if (l!=NULL)
1147  {
1148    SI_LINK_SET_CLOSE_P(l);
1149    ssiInfo *d = (ssiInfo *)l->data;
1150    if (d!=NULL)
1151    {
1152      if (d->send_quit_at_exit)
1153      {
1154        fputs("99\n",d->f_write);
1155        fflush(d->f_write);
1156      }
1157      d->quit_sent=1;
1158    }
1159  }
1160  return FALSE;
1161}
1162
1163BOOLEAN ssiClose(si_link l)
1164{
1165  if (l!=NULL)
1166  {
1167    SI_LINK_SET_CLOSE_P(l);
1168    ssiInfo *d = (ssiInfo *)l->data;
1169    if (d!=NULL)
1170    {
1171      // send quit signal
1172      if ((d->send_quit_at_exit)
1173      && (d->quit_sent==0))
1174      {
1175        fputs("99\n",d->f_write);
1176        fflush(d->f_write);
1177      }
1178      // clean ring
1179      if (d->r!=NULL) rKill(d->r);
1180      // did the child to stop ?
1181      si_waitpid(d->pid,NULL,WNOHANG);
1182      if ((d->pid!=0)
1183      && (kill(d->pid,0)==0)) // child is still running
1184      {
1185        struct timespec t;
1186        t.tv_sec=0;
1187        t.tv_nsec=100000000; // <=100 ms
1188        struct timespec rem;
1189        int r;
1190        loop
1191        {
1192          // wait till signal or time rem:
1193          r = nanosleep(&t, &rem);
1194          t = rem;
1195          // child finished:
1196          if (si_waitpid(d->pid,NULL,WNOHANG) != 0) break;
1197          // other signal, waited s>= 100 ms:
1198          if ((r==0) || (errno != EINTR)) break;
1199        }
1200        if (kill(d->pid,0) == 0) // pid still exists
1201        {
1202          kill(d->pid,15);
1203          t.tv_sec=5; // <=5s
1204          t.tv_nsec=0;
1205          loop
1206          {
1207            // wait till signal or time rem:
1208            r = nanosleep(&t, &rem);
1209            t = rem;
1210            // child finished:
1211            if (si_waitpid(d->pid,NULL,WNOHANG) != 0) break;
1212            // other signal, waited s>=  5 s:
1213            if ((r==0) || (errno != EINTR)) break;
1214          }
1215          if (kill(d->pid,0) == 0)
1216          {
1217            kill(d->pid,9); // just to be sure
1218            si_waitpid(d->pid,NULL,0);
1219          }
1220        }
1221      }
1222      if (d->f_read!=NULL) { s_close(d->f_read);d->f_read=NULL;}
1223      if (d->f_write!=NULL) { fclose(d->f_write); d->f_write=NULL; }
1224      if ((strcmp(l->mode,"tcp")==0)
1225      || (strcmp(l->mode,"fork")==0))
1226      {
1227        link_list hh=ssiToBeClosed;
1228        if (hh!=NULL)
1229        {
1230          if (hh->l==l)
1231          {
1232             ssiToBeClosed=(link_list)hh->next;
1233             omFreeSize(hh,sizeof(link_struct));
1234          }
1235          else while(hh->next!=NULL)
1236          {
1237            link_list hhh=(link_list)hh->next;
1238            if (hhh->l==l)
1239            {
1240              hh->next=hhh->next;
1241              omFreeSize(hhh,sizeof(link_struct));
1242              break;
1243            }
1244            else
1245              hh=(link_list)hh->next;
1246          }
1247        }
1248      }
1249      omFreeSize((ADDRESS)d,(sizeof *d));
1250    }
1251    l->data=NULL;
1252  }
1253  return FALSE;
1254}
1255
1256//**************************************************************************/
1257leftv ssiRead1(si_link l)
1258{
1259  ssiInfo *d = (ssiInfo *)l->data;
1260  leftv res=(leftv)omAlloc0Bin(sleftv_bin);
1261  int t=0;
1262  t=s_readint(d->f_read);
1263  //Print("got type %d\n",t);
1264  switch(t)
1265  {
1266    case 1:res->rtyp=INT_CMD;
1267           res->data=(char *)(long)ssiReadInt(d->f_read);
1268           break;
1269    case 2:res->rtyp=STRING_CMD;
1270           res->data=(char *)ssiReadString(d);
1271           break;
1272    case 3:res->rtyp=NUMBER_CMD;
1273           res->data=(char *)ssiReadNumber(d);
1274           break;
1275    case 4:res->rtyp=BIGINT_CMD;
1276           res->data=(char *)ssiReadBigInt(d);
1277           break;
1278    case 15:
1279    case 5:{
1280             d->r=ssiReadRing(d);
1281             if (d->r==NULL) return NULL;
1282             res->data=(char*)d->r;
1283             res->rtyp=RING_CMD;
1284             // we are in the top-level, so set the basering to d->r:
1285             if (d->r!=NULL)
1286             {
1287               if(ssiSetCurrRing(d->r)) { d->r=currRing; d->r->ref++; }
1288             }
1289             if (t==15) // setring
1290             {
1291               omFreeBin(res,sleftv_bin);
1292               return ssiRead1(l);
1293             }
1294           }
1295           break;
1296    case 6:res->rtyp=POLY_CMD;
1297           if (d->r==NULL) goto no_ring;
1298           res->data=(char*)ssiReadPoly(d);
1299           break;
1300    case 7:res->rtyp=IDEAL_CMD;
1301           if (d->r==NULL) goto no_ring;
1302           res->data=(char*)ssiReadIdeal(d);
1303           break;
1304    case 8:res->rtyp=MATRIX_CMD;
1305           if (d->r==NULL) goto no_ring;
1306           res->data=(char*)ssiReadMatrix(d);
1307           break;
1308    case 9:res->rtyp=VECTOR_CMD;
1309           if (d->r==NULL) goto no_ring;
1310           res->data=(char*)ssiReadPoly(d);
1311           break;
1312    case 10:res->rtyp=MODUL_CMD;
1313           if (d->r==NULL) goto no_ring;
1314           {
1315             int rk=s_readint(d->f_read);
1316             ideal M=ssiReadIdeal(d);
1317             M->rank=rk;
1318             res->data=(char*)M;
1319           }
1320           break;
1321    case 11:
1322           {
1323             res->rtyp=COMMAND;
1324             res->data=ssiReadCommand(l);
1325             int nok=res->Eval();
1326             if (nok) WerrorS("error in eval");
1327             break;
1328           }
1329    case 12: /*DEF_CMD*/
1330           {
1331             res->rtyp=0;
1332             res->name=(char *)ssiReadString(d);
1333             int nok=res->Eval();
1334             if (nok) WerrorS("error in name lookup");
1335             break;
1336           }
1337    case 13: res->rtyp=PROC_CMD;
1338             res->data=ssiReadProc(d);
1339             break;
1340    case 14: res->rtyp=LIST_CMD;
1341             res->data=ssiReadList(l);
1342             break;
1343    case 16: res->rtyp=NONE; res->data=NULL;
1344             break;
1345    case 17: res->rtyp=INTVEC_CMD;
1346             res->data=ssiReadIntvec(d);
1347             break;
1348    case 18: res->rtyp=INTMAT_CMD;
1349             res->data=ssiReadIntmat(d);
1350             break;
1351    case 19: res->rtyp=BIGINTMAT_CMD;
1352             res->data=ssiReadBigintmat(d);
1353             break;
1354    case 20: ssiReadBlackbox(res,l);
1355             break;
1356    case 21: ssiReadAttrib(res,l);
1357             break;
1358    // ------------
1359    case 98: // version
1360             {
1361                int n98_v,n98_m;
1362                BITSET n98_o1,n98_o2;
1363                n98_v=s_readint(d->f_read);
1364                n98_m=s_readint(d->f_read);
1365                n98_o1=s_readint(d->f_read);
1366                n98_o2=s_readint(d->f_read);
1367                if ((n98_v!=SSI_VERSION) ||(n98_m!=MAX_TOK))
1368                {
1369                  Print("incompatible versions of ssi: %d/%d vs %d/%d\n",
1370                                  SSI_VERSION,MAX_TOK,n98_v,n98_m);
1371                }
1372                #ifndef SING_NDEBUG
1373                if (TEST_OPT_DEBUG)
1374                  Print("// opening ssi-%d, MAX_TOK=%d\n",n98_v,n98_m);
1375                #endif
1376                si_opt_1=n98_o1;
1377                si_opt_2=n98_o2;
1378                omFreeBin(res,sleftv_bin);
1379                return ssiRead1(l);
1380             }
1381    case 99: omFreeBin(res,sleftv_bin); ssiClose(l); m2_end(0);
1382    case 0: if (s_iseof(d->f_read))
1383            {
1384              ssiClose(l);
1385            }
1386            res->rtyp=DEF_CMD;
1387            break;
1388    default: Werror("not implemented (t:%d)",t);
1389             omFreeBin(res,sleftv_bin);
1390             res=NULL;
1391             break;
1392  }
1393  // if currRing is required for the result, but lost
1394  // define "ssiRing%d" as currRing:
1395  if ((d->r!=NULL)
1396  && (currRing!=d->r)
1397  && (res->RingDependend()))
1398  {
1399    if(ssiSetCurrRing(d->r)) { d->r=currRing; d->r->ref++; }
1400  }
1401  return res;
1402no_ring: WerrorS("no ring");
1403  omFreeBin(res,sleftv_bin);
1404  return NULL;
1405}
1406//**************************************************************************/
1407BOOLEAN ssiSetRing(si_link l, ring r, BOOLEAN send)
1408{
1409  if(SI_LINK_W_OPEN_P(l)==0)
1410     if (slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL)) return TRUE;
1411  ssiInfo *d = (ssiInfo *)l->data;
1412  if (d->r!=r)
1413  {
1414    if (send)
1415    {
1416      fputs("15 ",d->f_write);
1417      ssiWriteRing(d,r);
1418    }
1419    d->r=r;
1420  }
1421  if (currRing!=r) rChangeCurrRing(r);
1422  return FALSE;
1423}
1424//**************************************************************************/
1425
1426BOOLEAN ssiWrite(si_link l, leftv data)
1427{
1428  if(SI_LINK_W_OPEN_P(l)==0)
1429     if (slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL)) return TRUE;
1430  ssiInfo *d = (ssiInfo *)l->data;
1431  d->level++;
1432  //FILE *fich=d->f;
1433  while (data!=NULL)
1434  {
1435    int tt=data->Typ();
1436    void *dd=data->Data();
1437    attr *aa=data->Attribute();
1438    BOOLEAN with_attr=FALSE;
1439    if (((*aa)!=NULL)||(data->flag!=0))
1440    {
1441      attr a=*aa;
1442      int n=0;
1443      while(a!=NULL) { n++; a=a->next;}
1444      fprintf(d->f_write,"21 %d %d ",data->flag,n);
1445      a=*aa;
1446    }
1447    if ((dd==NULL) && (data->name!=NULL) && (tt==0)) tt=DEF_CMD;
1448      // return pure undefined names as def
1449
1450    switch(tt /*data->Typ()*/)
1451    {
1452          case 0: /*error*/
1453          case NONE/* nothing*/:fputs("16 ",d->f_write);
1454                          break;
1455          case STRING_CMD: fputs("2 ",d->f_write);
1456                           ssiWriteString(d,(char *)dd);
1457                           break;
1458          case INT_CMD: fputs("1 ",d->f_write);
1459                        ssiWriteInt(d,(int)(long)dd);
1460                        break;
1461          case BIGINT_CMD:fputs("4 ",d->f_write);
1462                        ssiWriteBigInt(d,(number)dd);
1463                        break;
1464          case NUMBER_CMD:
1465                          if (d->r!=currRing)
1466                          {
1467                            fputs("15 ",d->f_write);
1468                            ssiWriteRing(d,currRing);
1469                            if (d->level<=1) fputc('\n',d->f_write);
1470                          }
1471                          fputs("3 ",d->f_write);
1472                          ssiWriteNumber(d,(number)dd);
1473                        break;
1474          case RING_CMD:fputs("5 ",d->f_write);
1475                        ssiWriteRing(d,(ring)dd);
1476                        break;
1477          case POLY_CMD:
1478          case VECTOR_CMD:
1479                        if (d->r!=currRing)
1480                        {
1481                          fputs("15 ",d->f_write);
1482                          ssiWriteRing(d,currRing);
1483                          if (d->level<=1) fputc('\n',d->f_write);
1484                        }
1485                        if(tt==POLY_CMD) fputs("6 ",d->f_write);
1486                        else             fputs("9 ",d->f_write);
1487                        ssiWritePoly(d,tt,(poly)dd);
1488                        break;
1489          case IDEAL_CMD:
1490          case MODUL_CMD:
1491          case MATRIX_CMD:
1492                        if (d->r!=currRing)
1493                        {
1494                          fputs("15 ",d->f_write);
1495                          ssiWriteRing(d,currRing);
1496                          if (d->level<=1) fputc('\n',d->f_write);
1497                        }
1498                        if(tt==IDEAL_CMD)       fputs("7 ",d->f_write);
1499                        else if(tt==MATRIX_CMD) fputs("8 ",d->f_write);
1500                        else
1501                        {
1502                          ideal M=(ideal)dd;
1503                          fprintf(d->f_write,"10 %d ",(int)M->rank);
1504                        }
1505                        ssiWriteIdeal(d,tt,(ideal)dd);
1506                        break;
1507          case COMMAND:
1508                   fputs("11 ",d->f_write);
1509                   ssiWriteCommand(l,(command)dd);
1510                   break;
1511          case DEF_CMD: /* not evaluated stuff in quotes */
1512                   fputs("12 ",d->f_write);
1513                   ssiWriteString(d,data->Name());
1514                   break;
1515          case PROC_CMD:
1516                   fputs("13 ",d->f_write);
1517                   ssiWriteProc(d,(procinfov)dd);
1518                   break;
1519          case LIST_CMD:
1520                   fputs("14 ",d->f_write);
1521                   ssiWriteList(l,(lists)dd);
1522                   break;
1523          case INTVEC_CMD:
1524                   fputs("17 ",d->f_write);
1525                   ssiWriteIntvec(d,(intvec *)dd);
1526                   break;
1527          case INTMAT_CMD:
1528                   fputs("18 ",d->f_write);
1529                   ssiWriteIntmat(d,(intvec *)dd);
1530                   break;
1531          case BIGINTMAT_CMD:
1532                   fputs("19 ",d->f_write);
1533                   ssiWriteBigintmat(d,(bigintmat *)dd);
1534                   break;
1535          default:
1536            if (tt>MAX_TOK)
1537            {
1538              blackbox *b=getBlackboxStuff(tt);
1539              fputs("20 ",d->f_write);
1540              b->blackbox_serialize(b,dd,l);
1541            }
1542            else
1543            {
1544              Werror("not implemented (t:%d, rtyp:%d)",tt, data->rtyp);
1545              d->level=0;
1546              return TRUE;
1547            }
1548            break;
1549    }
1550    if (d->level<=1) { fputc('\n',d->f_write); fflush(d->f_write); }
1551    data=data->next;
1552  }
1553  d->level--;
1554  return FALSE;
1555}
1556
1557BOOLEAN ssiGetDump(si_link l);
1558BOOLEAN ssiDump(si_link l);
1559
1560si_link_extension slInitSsiExtension(si_link_extension s)
1561{
1562  s->Open=ssiOpen;
1563  s->Close=ssiClose;
1564  s->Kill=ssiClose;
1565  s->Read=ssiRead1;
1566  s->Read2=(slRead2Proc)NULL;
1567  s->Write=ssiWrite;
1568  s->Dump=ssiDump;
1569  s->GetDump=ssiGetDump;
1570
1571  s->Status=slStatusSsi;
1572  s->SetRing=ssiSetRing;
1573  s->type="ssi";
1574  return s;
1575}
1576
1577const char* slStatusSsi(si_link l, const char* request)
1578{
1579  ssiInfo *d=(ssiInfo*)l->data;
1580  if (d==NULL) return "not open";
1581  if (((strcmp(l->mode,"fork")==0)
1582  ||(strcmp(l->mode,"tcp")==0)
1583  ||(strcmp(l->mode,"connect")==0))
1584  && (strcmp(request, "read") == 0))
1585  {
1586    fd_set  mask;
1587    struct timeval wt;
1588    if (s_isready(d->f_read)) return "ready";
1589    loop
1590    {
1591      /* Don't block. Return socket status immediately. */
1592      wt.tv_sec  = 0;
1593      wt.tv_usec = 0;
1594
1595      FD_ZERO(&mask);
1596      FD_SET(d->fd_read, &mask);
1597      //Print("test fd %d\n",d->fd_read);
1598    /* check with select: chars waiting: no -> not ready */
1599      switch (si_select(d->fd_read+1, &mask, NULL, NULL, &wt))
1600      {
1601        case 0: /* not ready */ return "not ready";
1602        case -1: /*error*/      return "error";
1603        case 1: /*ready ? */    break;
1604      }
1605    /* yes: read 1 char*/
1606    /* if \n, check again with select else ungetc(c), ready*/
1607      int c=s_getc(d->f_read);
1608      //Print("try c=%d\n",c);
1609      if (c== -1) return "eof"; /* eof or error */
1610      else if (isdigit(c))
1611      { s_ungetc(c,d->f_read); return "ready"; }
1612      else if (c>' ')
1613      {
1614        Werror("unknown char in ssiLink(%d)",c);
1615        return "error";
1616      }
1617      /* else: next char */
1618    }
1619  }
1620  else if (strcmp(request, "read") == 0)
1621  {
1622    if (SI_LINK_R_OPEN_P(l) && (!s_iseof(d->f_read)) && (s_isready(d->f_read))) return "ready";
1623    else return "not ready";
1624  }
1625  else if (strcmp(request, "write") == 0)
1626  {
1627    if (SI_LINK_W_OPEN_P(l)) return "ready";
1628    else return "not ready";
1629  }
1630  else return "unknown status request";
1631}
1632
1633int slStatusSsiL(lists L, int timeout)
1634{
1635// input: L: a list with links of type
1636//           ssi-connect, ssi-fork, ssi-tcp, MPtcp-fork or MPtcp-launch.
1637//           Note: Not every entry in L must be set.
1638//        timeout: timeout for select in micro-seconds
1639//           or -1 for infinity
1640//           or 0 for polling
1641// returns: ERROR (via Werror): L has wrong elements or link not open
1642//           -2: select returns an error
1643//           -1: the read state of all links is eof
1644//           0:  timeout (or polling): none ready,
1645//           i>0: (at least) L[i] is ready
1646  si_link l;
1647  ssiInfo *d;
1648  int d_fd;
1649  fd_set  mask, fdmask;
1650  FD_ZERO(&fdmask);
1651  FD_ZERO(&mask);
1652  int max_fd=0; /* 1 + max fd in fd_set */
1653
1654  /* timeout */
1655  struct timeval wt;
1656  struct timeval *wt_ptr=&wt;
1657  int startingtime = getRTimer()/TIMER_RESOLUTION;  // in seconds
1658  if (timeout== -1)
1659  {
1660    wt_ptr=NULL;
1661  }
1662  else
1663  {
1664    wt.tv_sec  = timeout / 1000000;
1665    wt.tv_usec = timeout % 1000000;
1666  }
1667
1668  /* auxiliary variables */
1669  int i;
1670  int j;
1671  int k;
1672  int s;
1673  char fdmaskempty;
1674
1675  /* check the links and fill in fdmask */
1676  /* check ssi links for ungetc_buf */
1677  for(i=L->nr; i>=0; i--)
1678  {
1679    if (L->m[i].Typ()!=DEF_CMD)
1680    {
1681      if (L->m[i].Typ()!=LINK_CMD)
1682      { WerrorS("all elements must be of type link"); return -2;}
1683      l=(si_link)L->m[i].Data();
1684      if(SI_LINK_OPEN_P(l)==0)
1685      { WerrorS("all links must be open"); return -2;}
1686      if (((strcmp(l->m->type,"ssi")!=0) && (strcmp(l->m->type,"MPtcp")!=0))
1687      || ((strcmp(l->mode,"fork")!=0) && (strcmp(l->mode,"tcp")!=0)
1688        && (strcmp(l->mode,"launch")!=0) && (strcmp(l->mode,"connect")!=0)))
1689      {
1690        WerrorS("all links must be of type ssi:fork, ssi:tcp, ssi:connect");
1691        return -2;
1692      }
1693      if (strcmp(l->m->type,"ssi")==0)
1694      {
1695        d=(ssiInfo*)l->data;
1696        d_fd=d->fd_read;
1697        if (!s_isready(d->f_read))
1698        {
1699          FD_SET(d_fd, &fdmask);
1700          if (d_fd > max_fd) max_fd=d_fd;
1701        }
1702        else
1703          return i+1;
1704      }
1705      else
1706      {
1707        Werror("wrong link type >>%s<<",l->m->type);
1708        return -2;
1709      }
1710    }
1711  }
1712  max_fd++;
1713
1714do_select:
1715  /* copy fdmask to mask */
1716  FD_ZERO(&mask);
1717  for(k = 0; k < max_fd; k++)
1718  {
1719    if(FD_ISSET(k, &fdmask))
1720    {
1721      FD_SET(k, &mask);
1722    }
1723  }
1724
1725  /* check with select: chars waiting: no -> not ready */
1726  s = si_select(max_fd, &mask, NULL, NULL, wt_ptr);
1727  if (s==-1)
1728  {
1729    WerrorS("error in select call");
1730    return -2; /*error*/
1731  }
1732  if (s==0)
1733  {
1734    return 0; /*poll: not ready */
1735  }
1736  else /* s>0, at least one ready  (the number of fd which are ready is s)*/
1737  {
1738    j=0;
1739    while (j<=max_fd) { if (FD_ISSET(j,&mask)) break; j++; }
1740    for(i=L->nr; i>=0; i--)
1741    {
1742      if (L->m[i].rtyp==LINK_CMD)
1743      {
1744        l=(si_link)L->m[i].Data();
1745        if (strcmp(l->m->type,"ssi")==0)
1746        {
1747          d=(ssiInfo*)l->data;
1748          d_fd=d->fd_read;
1749          if(j==d_fd) break;
1750        }
1751        else
1752        {
1753          Werror("wrong link type >>%s<<",l->m->type);
1754          return -2;
1755        }
1756      }
1757    }
1758    // only ssi links:
1759    loop
1760    {
1761      /* yes: read 1 char*/
1762      /* if \n, check again with select else ungetc(c), ready*/
1763      /* setting: d: current ssiInfo, j current fd, i current entry in L*/
1764      int c=s_getc(d->f_read);
1765      //Print("try c=%d\n",c);
1766      if (c== -1) /* eof */
1767      {
1768        FD_CLR(j,&fdmask);
1769        fdmaskempty = 1;
1770        for(k = 0; k < max_fd; k++)
1771        {
1772          if(FD_ISSET(k, &fdmask))
1773          {
1774            fdmaskempty = 0;
1775            break;
1776          }
1777        }
1778        if(fdmaskempty)
1779        {
1780          return -1;
1781        }
1782        if(timeout != -1)
1783        {
1784          timeout = si_max(0,
1785             timeout - 1000000*(getRTimer()/TIMER_RESOLUTION - startingtime));
1786          wt.tv_sec  = timeout / 1000000;
1787          wt.tv_usec = (timeout % 1000000);
1788        }
1789        goto do_select;
1790      }
1791
1792      else if (isdigit(c))
1793      { s_ungetc(c,d->f_read); return i+1; }
1794      else if (c>' ')
1795      {
1796        Werror("unknown char in ssiLink(%d)",c);
1797        return -2;
1798      }
1799      /* else: next char */
1800      goto do_select;
1801    }
1802  }
1803}
1804
1805int ssiBatch(const char *host, const char * port)
1806/* return 0 on success, >0 else*/
1807{
1808  si_link l=(si_link) omAlloc0Bin(sip_link_bin);
1809  char *buf=(char*)omAlloc(256);
1810  sprintf(buf,"ssi:connect %s:%s",host,port);
1811  slInit(l, buf);
1812  omFreeSize(buf,256);
1813  if (slOpen(l,SI_LINK_OPEN,NULL)) return 1;
1814  SI_LINK_SET_RW_OPEN_P(l);
1815
1816  idhdl id = enterid(omStrDup("link_ll"), 0, LINK_CMD, &IDROOT, FALSE);
1817  IDLINK(id) = l;
1818
1819  loop
1820  {
1821    leftv h=ssiRead1(l); /*contains an exit.... */
1822    if (feErrors != NULL && *feErrors != '\0')
1823    {
1824      // handle errors:
1825      PrintS(feErrors); /* currently quite simple */
1826      *feErrors = '\0';
1827    }
1828    ssiWrite(l,h);
1829    h->CleanUp();
1830    omFreeBin(h, sleftv_bin);
1831  }
1832  /* never reached*/
1833  exit(0);
1834}
1835
1836static int ssiReserved_P=0;
1837static int ssiReserved_sockfd;
1838static  struct sockaddr_in ssiResverd_serv_addr;
1839static int  ssiReserved_Clients;
1840int ssiReservePort(int clients)
1841{
1842  if (ssiReserved_P!=0)
1843  {
1844    WerrorS("ERROR already a reverved port requested");
1845    return 0;
1846  }
1847  int portno;
1848  ssiReserved_sockfd = socket(AF_INET, SOCK_STREAM, 0);
1849  if(ssiReserved_sockfd < 0)
1850  {
1851    WerrorS("ERROR opening socket");
1852    return 0;
1853  }
1854  memset((char *) &ssiResverd_serv_addr,0, sizeof(ssiResverd_serv_addr));
1855  portno = 1025;
1856  ssiResverd_serv_addr.sin_family = AF_INET;
1857  ssiResverd_serv_addr.sin_addr.s_addr = INADDR_ANY;
1858  do
1859  {
1860    portno++;
1861    ssiResverd_serv_addr.sin_port = htons(portno);
1862    if(portno > 50000)
1863    {
1864      WerrorS("ERROR on binding (no free port available?)");
1865      return 0;
1866    }
1867  }
1868  while(bind(ssiReserved_sockfd, (struct sockaddr *) &ssiResverd_serv_addr, sizeof(ssiResverd_serv_addr)) < 0);
1869  ssiReserved_P=portno;
1870  listen(ssiReserved_sockfd,clients);
1871  ssiReserved_Clients=clients;
1872  return portno;
1873}
1874
1875extern si_link_extension si_link_root;
1876si_link ssiCommandLink()
1877{
1878  if (ssiReserved_P==0)
1879  {
1880    WerrorS("ERROR no reverved port requested");
1881    return NULL;
1882  }
1883  struct sockaddr_in cli_addr;
1884  int clilen = sizeof(cli_addr);
1885  int newsockfd = si_accept(ssiReserved_sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
1886  if(newsockfd < 0)
1887  {
1888    Werror("ERROR on accept (errno=%d)",errno);
1889    return NULL;
1890  }
1891  si_link l=(si_link) omAlloc0Bin(sip_link_bin);
1892  si_link_extension s = si_link_root;
1893  si_link_extension prev = s;
1894  while (strcmp(s->type, "ssi") != 0)
1895  {
1896    if (s->next == NULL)
1897    {
1898      prev = s;
1899      s = NULL;
1900      break;
1901    }
1902    else
1903    {
1904      s = s->next;
1905    }
1906  }
1907  if (s != NULL)
1908    l->m = s;
1909  else
1910  {
1911    si_link_extension ns = (si_link_extension)omAlloc0Bin(s_si_link_extension_bin);
1912    prev->next=slInitSsiExtension(ns);
1913    l->m = prev->next;
1914  }
1915  l->name=omStrDup("");
1916  l->mode=omStrDup("tcp");
1917  l->ref=1;
1918  ssiInfo *d=(ssiInfo*)omAlloc0(sizeof(ssiInfo));
1919  l->data=d;
1920  d->fd_read = newsockfd;
1921  d->fd_write = newsockfd;
1922  d->f_read = s_open(newsockfd);
1923  d->f_write = fdopen(newsockfd, "w");
1924  SI_LINK_SET_RW_OPEN_P(l);
1925  ssiReserved_Clients--;
1926  if (ssiReserved_Clients<=0)
1927  {
1928    ssiReserved_P=0;
1929    si_close(ssiReserved_sockfd);
1930  }
1931  return l;
1932}
1933/*---------------------------------------------------------------------*/
1934/**
1935 * @brief additional default signal handler
1936
1937  // some newer Linux version cannot have SIG_IGN for SIGCHLD,
1938  // so use this nice routine here:
1939  //  SuSe 9.x reports -1 always
1940  //  Redhat 9.x/FC x reports sometimes -1
1941  // see also: hpux_system
1942  // also needed by getrusage (timer etc.)
1943
1944 @param[in] sig
1945**/
1946/*---------------------------------------------------------------------*/
1947void sig_chld_hdl(int)
1948{
1949  pid_t kidpid;
1950  int status;
1951
1952  loop
1953  {
1954    kidpid = si_waitpid(-1, &status, WNOHANG);
1955    if (kidpid==-1)
1956    {
1957      /* continue on interruption (EINTR): */
1958      if (errno == EINTR) continue;
1959      /* break on anything else (EINVAL or ECHILD according to manpage): */
1960      break;
1961    }
1962    else if (kidpid==0) break; /* no more children to process, so break */
1963
1964    //printf("Child %ld terminated\n", kidpid);
1965    link_list hh=ssiToBeClosed;
1966    while((hh!=NULL)&&(ssiToBeClosed_inactive))
1967    {
1968      if((hh->l!=NULL) && (hh->l->m->Open==ssiOpen))
1969      {
1970        ssiInfo *d = (ssiInfo *)hh->l->data;
1971        if(d->pid==kidpid)
1972        {
1973          if(ssiToBeClosed_inactive)
1974          {
1975            ssiToBeClosed_inactive=FALSE;
1976            slClose(hh->l);
1977            ssiToBeClosed_inactive=TRUE;
1978            break;
1979          }
1980          else break;
1981        }
1982        else hh=(link_list)hh->next;
1983      }
1984      else hh=(link_list)hh->next;
1985    }
1986  }
1987}
1988
1989static BOOLEAN DumpSsiIdhdl(si_link l, idhdl h)
1990{
1991  int type_id = IDTYP(h);
1992
1993  // C-proc not to be dumped, also LIB-proc not
1994  if (type_id == PROC_CMD)
1995  {
1996    if (IDPROC(h)->language == LANG_C) return FALSE;
1997    if (IDPROC(h)->libname != NULL) return FALSE;
1998  }
1999  // do not dump links
2000  if (type_id == LINK_CMD) return FALSE;
2001
2002  // do not dump ssi internal rings: ssiRing*
2003  if ((type_id == RING_CMD) && (strncmp(IDID(h),"ssiRing",7)==0))
2004    return FALSE;
2005
2006  command D=(command)omAlloc0(sizeof(*D));
2007  sleftv tmp;
2008  memset(&tmp,0,sizeof(tmp));
2009  tmp.rtyp=COMMAND;
2010  tmp.data=D;
2011
2012  if (type_id == PACKAGE_CMD)
2013  {
2014    // do not dump Top, Standard
2015    if ((strcmp(IDID(h), "Top") == 0)
2016    || (strcmp(IDID(h), "Standard") == 0))
2017    {
2018      omFreeSize(D,sizeof(*D));
2019      return FALSE;
2020    }
2021    package p=(package)IDDATA(h);
2022    // dump Singular-packages as LIB("...");
2023    if (p->language==LANG_SINGULAR)
2024    {
2025      D->op=LOAD_CMD;
2026      D->argc=2;
2027      D->arg1.rtyp=STRING_CMD;
2028      D->arg1.data=p->libname;
2029      D->arg2.rtyp=STRING_CMD;
2030      D->arg2.data=(char*)"with";
2031      ssiWrite(l,&tmp);
2032      omFreeSize(D,sizeof(*D));
2033      return FALSE;
2034    }
2035    // dump Singular-packages as load("...");
2036    else if (p->language==LANG_C)
2037    {
2038      D->op=LOAD_CMD;
2039      D->argc=1;
2040      D->arg1.rtyp=STRING_CMD;
2041      D->arg1.data=p->libname;
2042      ssiWrite(l,&tmp);
2043      omFreeSize(D,sizeof(*D));
2044      return FALSE;
2045    }
2046  }
2047
2048  // put type and name
2049  //Print("generic dump:%s,%s\n",IDID(h),Tok2Cmdname(IDTYP(h)));
2050  D->op='=';
2051  D->argc=2;
2052  D->arg1.rtyp=DEF_CMD;
2053  D->arg1.name=IDID(h);
2054  D->arg2.rtyp=IDTYP(h);
2055  D->arg2.data=IDDATA(h);
2056  ssiWrite(l,&tmp);
2057  omFreeSize(D,sizeof(*D));
2058  return FALSE;
2059}
2060static BOOLEAN ssiDumpIter(si_link l, idhdl h)
2061{
2062  if (h == NULL) return FALSE;
2063
2064  if (ssiDumpIter(l, IDNEXT(h))) return TRUE;
2065
2066  // need to set the ring before writing it, otherwise we get in
2067  // trouble with minpoly
2068  if (IDTYP(h) == RING_CMD)
2069    rSetHdl(h);
2070
2071  if (DumpSsiIdhdl(l, h)) return TRUE;
2072
2073  // do not dump ssi internal rings: ssiRing*
2074  // but dump objects of all other rings
2075  if ((IDTYP(h) == RING_CMD)
2076  && (strncmp(IDID(h),"ssiRing",7)!=0))
2077    return ssiDumpIter(l, IDRING(h)->idroot);
2078  else
2079    return FALSE;
2080}
2081BOOLEAN ssiDump(si_link l)
2082{
2083  idhdl h = IDROOT, rh = currRingHdl;
2084  BOOLEAN status = ssiDumpIter(l, h);
2085
2086  //if (! status ) status = DumpAsciiMaps(fd, h, NULL);
2087
2088  if (currRingHdl != rh) rSetHdl(rh);
2089  //fprintf(fd, "option(set, intvec(%d, %d));\n", si_opt_1, si_opt_2);
2090
2091  return status;
2092}
2093BOOLEAN ssiGetDump(si_link l)
2094{
2095  ssiInfo *d=(ssiInfo*)l->data;
2096  loop
2097  {
2098    if (!SI_LINK_OPEN_P(l)) break;
2099    if (s_iseof(d->f_read)) break;
2100    leftv h=ssiRead1(l); /*contains an exit.... */
2101    if (feErrors != NULL && *feErrors != '\0')
2102    {
2103      // handle errors:
2104      PrintS(feErrors); /* currently quite simple */
2105      return TRUE;
2106      *feErrors = '\0';
2107    }
2108    h->CleanUp();
2109    omFreeBin(h, sleftv_bin);
2110  }
2111  return FALSE;
2112}
2113// ----------------------------------------------------------------
2114// format
2115// 1 int %d
2116// 2 string <len> %s
2117// 3 number
2118// 4 bigint 4 %d or 3 <mpz_t>
2119// 5 ring
2120// 6 poly
2121// 7 ideal
2122// 8 matrix
2123// 9 vector
2124// 10 module
2125// 11 command
2126// 12 def <len> %s
2127// 13 proc <len> %s
2128// 14 list %d <elem1> ....
2129// 15 setring .......
2130// 16 nothing
2131// 17 intvec <len> ...
2132// 18 intmat
2133// 19 bigintmat <r> <c> ...
2134// 20 blackbox <name> 1 <len> ...
2135// 21 attrib <bit-attrib> <len> <a-name1> <val1>... <data>
2136//
2137// 98: verify version: <ssi-version> <MAX_TOK> <OPT1> <OPT2>
2138// 99: quit Singular
Note: See TracBrowser for help on using the repository browser.