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

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