source: git/Singular/links/ssiLink.cc @ b2eee6

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