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

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