source: git/Singular/links/ssiLink.cc @ 190da3

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