1 /****************************************
2 * * Computer Algebra System SINGULAR *
3 * ****************************************/
4
5 /*
6 * ABSTRACT: ascii links (standard)
7 */
8
9 #include "kernel/mod2.h"
10 #include "misc/options.h"
11
12 #include "Singular/tok.h"
13 #include "Singular/subexpr.h"
14 #include "Singular/ipshell.h"
15 #include "Singular/ipid.h"
16 #include "Singular/fevoices.h"
17 #include "kernel/oswrapper/feread.h"
18 #include "Singular/ipshell.h"
19 #include "Singular/links/silink.h"
20
21 /* declarations */
22 static BOOLEAN DumpAscii(FILE *fd, idhdl h,char ***list_of_libs);
23 static BOOLEAN DumpAsciiIdhdl(FILE *fd, idhdl h,char ***list_of_libs);
24 static const char* GetIdString(idhdl h);
25 static int DumpRhs(FILE *fd, idhdl h);
26 static BOOLEAN DumpQring(FILE *fd, idhdl h);
27 static BOOLEAN DumpNCring(FILE *fd, idhdl h);
28 static BOOLEAN DumpAsciiMaps(FILE *fd, idhdl h, idhdl rhdl);
29 static BOOLEAN CollectLibs(char *name, char ***list_of_libs);
30 //static BOOLEAN DumpLibs(FILE *fd, char ***list_of_libs);
31
32 EXTERN_VAR si_link_extension si_link_root;
33
34 /* =============== ASCII ============================================= */
slOpenAscii(si_link l,short flag,leftv)35 BOOLEAN slOpenAscii(si_link l, short flag, leftv /*h*/)
36 {
37 const char *mode;
38 if (flag & SI_LINK_OPEN)
39 {
40 if (l->mode[0] != '\0' && (strcmp(l->mode, "r") == 0))
41 flag = SI_LINK_READ;
42 else flag = SI_LINK_WRITE;
43 }
44
45 if (flag == SI_LINK_READ) mode = "r";
46 else if (strcmp(l->mode, "w") == 0) mode = "w";
47 else mode = "a";
48
49
50 if (l->name[0] == '\0')
51 {
52 // stdin or stdout
53 if (flag == SI_LINK_READ)
54 {
55 l->data = (void *) stdin;
56 mode = "r";
57 }
58 else
59 {
60 l->data = (void *) stdout;
61 mode = "a";
62 }
63 }
64 else
65 {
66 // normal ascii link to a file
67 FILE *outfile;
68 char *filename=l->name;
69
70 if(filename[0]=='>')
71 {
72 if (filename[1]=='>')
73 {
74 filename+=2;
75 mode = "a";
76 }
77 else
78 {
79 filename++;
80 mode="w";
81 }
82 }
83 outfile=myfopen(filename,mode);
84 if (outfile!=NULL)
85 l->data = (void *) outfile;
86 else
87 return TRUE;
88 }
89
90 omFree(l->mode);
91 l->mode = omStrDup(mode);
92 SI_LINK_SET_OPEN_P(l, flag);
93 return FALSE;
94 }
95
slCloseAscii(si_link l)96 BOOLEAN slCloseAscii(si_link l)
97 {
98 SI_LINK_SET_CLOSE_P(l);
99 if (l->name[0] != '\0')
100 {
101 return (fclose((FILE *)l->data)!=0);
102 }
103 return FALSE;
104 }
105
slReadAscii2(si_link l,leftv pr)106 leftv slReadAscii2(si_link l, leftv pr)
107 {
108 FILE * fp=(FILE *)l->data;
109 char * buf=NULL;
110 if (fp!=NULL && l->name[0] != '\0')
111 {
112 fseek(fp,0L,SEEK_END);
113 long len=ftell(fp);
114 if (len<0) len=0;
115 fseek(fp,0L,SEEK_SET);
116 buf=(char *)omAlloc((int)len+1);
117 if (BVERBOSE(V_READING))
118 Print("//Reading %ld chars\n",len);
119 if (len>0) myfread( buf, len, 1, fp);
120 buf[len]='\0';
121 }
122 else
123 {
124 if (pr->Typ()==STRING_CMD)
125 {
126 buf=(char *)omAlloc(80);
127 fe_fgets_stdin((char *)pr->Data(),buf,80);
128 }
129 else
130 {
131 WerrorS("read(<link>,<string>) expected");
132 buf=omStrDup("");
133 }
134 }
135 leftv v=(leftv)omAlloc0Bin(sleftv_bin);
136 v->rtyp=STRING_CMD;
137 v->data=buf;
138 return v;
139 }
140
slReadAscii(si_link l)141 leftv slReadAscii(si_link l)
142 {
143 sleftv tmp;
144 memset(&tmp,0,sizeof(sleftv));
145 tmp.rtyp=STRING_CMD;
146 tmp.data=(void*) "? ";
147 return slReadAscii2(l,&tmp);
148 }
149
slWriteAscii(si_link l,leftv v)150 BOOLEAN slWriteAscii(si_link l, leftv v)
151 {
152 FILE *outfile=(FILE *)l->data;
153 BOOLEAN err=FALSE;
154 char *s;
155 while (v!=NULL)
156 {
157 switch(v->Typ())
158 {
159 case IDEAL_CMD:
160 case MODUL_CMD:
161 case MATRIX_CMD:
162 {
163 ideal I=(ideal)v->Data();
164 for(int i=0;i<IDELEMS(I);i++)
165 {
166 char *s=pString(I->m[i]);
167 fwrite(s,strlen(s),1,outfile);
168 omFree(s);
169 if (i<IDELEMS(I)-1) fwrite(",",1,1,outfile);
170 }
171 break;
172 }
173 default:
174 s = v->String();
175 // free v ??
176 if (s!=NULL)
177 {
178 fputs(s,outfile);
179 fputc('\n',outfile);
180 omFree((ADDRESS)s);
181 }
182 else
183 {
184 WerrorS("cannot convert to string");
185 err=TRUE;
186 }
187 }
188 v = v->next;
189 }
190 fflush(outfile);
191 return err;
192 }
193
slStatusAscii(si_link l,const char * request)194 const char* slStatusAscii(si_link l, const char* request)
195 {
196 if (strcmp(request, "read") == 0)
197 {
198 if (SI_LINK_R_OPEN_P(l)) return "ready";
199 else return "not ready";
200 }
201 else if (strcmp(request, "write") == 0)
202 {
203 if (SI_LINK_W_OPEN_P(l)) return "ready";
204 else return "not ready";
205 }
206 else return "unknown status request";
207 }
208
209 /*------------------ Dumping in Ascii format -----------------------*/
210
slDumpAscii(si_link l)211 BOOLEAN slDumpAscii(si_link l)
212 {
213 FILE *fd = (FILE *) l->data;
214 idhdl h = IDROOT, rh = currRingHdl;
215 char **list_of_libs=NULL;
216 BOOLEAN status = DumpAscii(fd, h, &list_of_libs);
217
218 if (! status ) status = DumpAsciiMaps(fd, h, NULL);
219
220 if (currRingHdl != rh) rSetHdl(rh);
221 fprintf(fd, "option(set, intvec(%d, %d));\n", si_opt_1, si_opt_2);
222 char **p=list_of_libs;
223 if (p!=NULL)
224 {
225 while((*p!=NULL) && (*p!=(char*)1))
226 {
227 fprintf(fd,"load(\"%s\",\"try\");\n",*p);
228 p++;
229 }
230 omFree(list_of_libs);
231 }
232 fputs("RETURN();\n",fd);
233 fflush(fd);
234
235 return status;
236 }
237
238 // we do that recursively, to dump ids in the the order in which they
239 // were actually defined
DumpAscii(FILE * fd,idhdl h,char *** list_of_libs)240 static BOOLEAN DumpAscii(FILE *fd, idhdl h, char ***list_of_libs)
241 {
242 if (h == NULL) return FALSE;
243
244 if (DumpAscii(fd, IDNEXT(h),list_of_libs)) return TRUE;
245
246 // need to set the ring before writing it, otherwise we get in
247 // trouble with minpoly
248 if (IDTYP(h) == RING_CMD)
249 rSetHdl(h);
250
251 if (DumpAsciiIdhdl(fd, h,list_of_libs)) return TRUE;
252
253 if (IDTYP(h) == RING_CMD)
254 return DumpAscii(fd, IDRING(h)->idroot,list_of_libs);
255 else
256 return FALSE;
257 }
258
DumpAsciiMaps(FILE * fd,idhdl h,idhdl rhdl)259 static BOOLEAN DumpAsciiMaps(FILE *fd, idhdl h, idhdl rhdl)
260 {
261 if (h == NULL) return FALSE;
262 if (DumpAsciiMaps(fd, IDNEXT(h), rhdl)) return TRUE;
263
264 if (IDTYP(h) == RING_CMD)
265 return DumpAsciiMaps(fd, IDRING(h)->idroot, h);
266 else if (IDTYP(h) == MAP_CMD)
267 {
268 char *rhs;
269 rSetHdl(rhdl);
270 rhs = h->String();
271
272 if (fprintf(fd, "setring %s;\n", IDID(rhdl)) == EOF) return TRUE;
273 if (fprintf(fd, "%s %s = %s, %s;\n", Tok2Cmdname(MAP_CMD), IDID(h),
274 IDMAP(h)->preimage, rhs) == EOF)
275 {
276 omFree(rhs);
277 return TRUE;
278 }
279 else
280 {
281 omFree(rhs);
282 return FALSE;
283 }
284 }
285 else return FALSE;
286 }
287
DumpAsciiIdhdl(FILE * fd,idhdl h,char *** list_of_libs)288 static BOOLEAN DumpAsciiIdhdl(FILE *fd, idhdl h, char ***list_of_libs)
289 {
290 const char *type_str = GetIdString(h);
291 int type_id = IDTYP(h);
292
293 if (type_id == PACKAGE_CMD)
294 {
295 if (strcmp(IDID(h),"Top")==0) return FALSE; // do not dump "Top"
296 if (IDPACKAGE(h)->language==LANG_SINGULAR) return FALSE;
297 if (IDPACKAGE(h)->language==LANG_MIX) return FALSE;
298 }
299 if (type_id == CRING_CMD)
300 {
301 // do not dump the default CRINGs:
302 if (strcmp(IDID(h),"QQ")==0) return FALSE;
303 if (strcmp(IDID(h),"ZZ")==0) return FALSE;
304 #ifdef SINGULAR_4_2
305 if (strcmp(IDID(h),"AE")==0) return FALSE;
306 if (strcmp(IDID(h),"QAE")==0) return FALSE;
307 #endif
308 }
309
310 // we do not throw an error if a wrong type was attempted to be dumped
311 if (type_str == NULL)
312 return FALSE;
313
314 // handle nc-rings separately
315 if ((type_id == RING_CMD)&&(rIsNCRing(IDRING(h))))
316 return DumpNCring(fd,h);
317
318 // handle qrings separately
319 if ((type_id == RING_CMD)&&(IDRING(h)->qideal!=NULL))
320 return DumpQring(fd, h);
321
322 // C-proc not to be dumped
323 if ((type_id == PROC_CMD) && (IDPROC(h)->language == LANG_C))
324 return FALSE;
325
326 // handle libraries
327 if ((type_id == PROC_CMD)
328 && (IDPROC(h)->language == LANG_SINGULAR)
329 && (IDPROC(h)->libname!=NULL))
330 return CollectLibs(IDPROC(h)->libname,list_of_libs);
331
332 // put type and name
333 if (fprintf(fd, "%s %s", type_str, IDID(h)) == EOF)
334 return TRUE;
335 // for matricies, append the dimension
336 if (type_id == MATRIX_CMD)
337 {
338 ideal id = IDIDEAL(h);
339 if (fprintf(fd, "[%d][%d]", id->nrows, id->ncols)== EOF) return TRUE;
340 }
341 else if (type_id == INTMAT_CMD)
342 {
343 if (fprintf(fd, "[%d][%d]", IDINTVEC(h)->rows(), IDINTVEC(h)->cols())
344 == EOF) return TRUE;
345 }
346 else if (type_id == SMATRIX_CMD)
347 {
348 ideal id = IDIDEAL(h);
349 if (fprintf(fd, "[%d][%d]", (int)id->rank, IDELEMS(id))== EOF) return TRUE;
350 }
351
352 if (type_id == PACKAGE_CMD)
353 {
354 return (fputs(";\n",fd) == EOF);
355 }
356
357 // write the equal sign
358 if (fputs(" = ",fd) == EOF) return TRUE;
359
360 // and the right hand side
361 if (DumpRhs(fd, h) == EOF) return TRUE;
362
363 // semicolon und tschuess
364 if (fputs(";\n",fd) == EOF) return TRUE;
365
366 return FALSE;
367 }
368
GetIdString(idhdl h)369 static const char* GetIdString(idhdl h)
370 {
371 int type = IDTYP(h);
372
373 switch(type)
374 {
375 case LIST_CMD:
376 //{
377 //
378 //
379 // lists l = IDLIST(h);
380 // int i, nl = l->nr + 1;
381 //
382 // for (i=0; i<nl; i++)
383 // if (GetIdString((idhdl) &(l->m[i])) == NULL) return NULL;
384 // break;
385 //}
386 case CRING_CMD:
387 #ifdef SINGULAR_4_2
388 case CNUMBER_CMD:
389 case CMATRIX_CMD:
390 #endif
391 case BIGINT_CMD:
392 case PACKAGE_CMD:
393 case INT_CMD:
394 case INTVEC_CMD:
395 case INTMAT_CMD:
396 case STRING_CMD:
397 case RING_CMD:
398 case QRING_CMD:
399 case PROC_CMD:
400 case NUMBER_CMD:
401 case POLY_CMD:
402 case IDEAL_CMD:
403 case VECTOR_CMD:
404 case MODUL_CMD:
405 case MATRIX_CMD:
406 case SMATRIX_CMD:
407 return Tok2Cmdname(type);
408
409 case MAP_CMD:
410 case LINK_CMD:
411 return NULL;
412
413 default:
414 Warn("Error dump data of type %s", Tok2Cmdname(IDTYP(h)));
415 return NULL;
416 }
417 }
418
DumpNCring(FILE * fd,idhdl h)419 static BOOLEAN DumpNCring(FILE *fd, idhdl h)
420 {
421 char *ring_str = h->String();
422 ring r=IDRING(h);
423
424 if (rIsPluralRing(r))
425 {
426 if (fprintf(fd, "ring temp_ring = %s;\n", ring_str)
427 == EOF) return TRUE;
428 if (fprintf(fd, "ideal temp_C = %s;\n",
429 iiStringMatrix((matrix) r->GetNC()->C, 2, r, n_GetChar(r->cf)))
430 == EOF) return TRUE;
431 if (fprintf(fd, "ideal temp_D = %s;\n",
432 iiStringMatrix((matrix) r->GetNC()->D, 2, r, n_GetChar(r->cf)))
433 == EOF) return TRUE;
434 if (fprintf(fd, "def %s = nc_algebra(temp_C,temp_D);\n",IDID(h)) == EOF)
435 return TRUE;
436 if (fputs("kill temp_ring;\n",fd) == EOF) return TRUE;
437 }
438 if (rIsLPRing(r))
439 {
440 //if (fprintf(fd, "ring %s = %s;\n", IDID(h), ring_str) == EOF) return TRUE;
441 //if (fprintf(fd, "attrib(%s,\"isLetterplaceRing\",%d);\n",IDID(h),r->isLPring) ==EOF) return TRUE;
442 Warn("cannot write LP ring %s",IDID(h));
443 return TRUE;
444 }
445 omFree(ring_str);
446 return FALSE;
447 }
448
DumpQring(FILE * fd,idhdl h)449 static BOOLEAN DumpQring(FILE *fd, idhdl h)
450 {
451 char *ring_str = h->String();
452 ring r=IDRING(h);
453 if (fprintf(fd, "ring temp_ring = %s;\n", ring_str) == EOF) return TRUE;
454 if (fprintf(fd, "ideal temp_ideal = %s;\n",
455 iiStringMatrix((matrix) r->qideal, 1, currRing, n_GetChar(r->cf)))
456 == EOF) return TRUE;
457 if (fputs("attrib(temp_ideal, \"isSB\", 1);\n",fd) == EOF) return TRUE;
458 if (fprintf(fd, "qring %s = temp_ideal;\n",IDID(h)) == EOF)
459 return TRUE;
460 if (fputs("kill temp_ring;\n",fd) == EOF) return TRUE;
461 else
462 {
463 omFree(ring_str);
464 return FALSE;
465 }
466 }
467
CollectLibs(char * name,char *** list_of_libs)468 static BOOLEAN CollectLibs(char *name, char *** list_of_libs)
469 {
470 if (*list_of_libs==NULL)
471 {
472 #define MAX_LIBS 256
473 (*list_of_libs)=(char**)omAlloc0(MAX_LIBS*sizeof(char**));
474 (*list_of_libs)[0]=name;
475 (*list_of_libs)[MAX_LIBS-1]=(char*)1;
476 return FALSE;
477 }
478 else
479 {
480 char **p=*list_of_libs;
481 while (((*p)!=NULL)&&((*p!=(char*)1)))
482 {
483 if (strcmp((*p),name)==0) return FALSE;
484 p++;
485 }
486 if (*p==(char*)1)
487 {
488 WerrorS("too many libs");
489 return TRUE;
490 }
491 else
492 {
493 *p=name;
494 }
495 }
496 return FALSE;
497 }
498
499
DumpRhs(FILE * fd,idhdl h)500 static int DumpRhs(FILE *fd, idhdl h)
501 {
502 int type_id = IDTYP(h);
503
504 if (type_id == LIST_CMD)
505 {
506 lists l = IDLIST(h);
507 int i, nl = l->nr;
508
509 fputs("list(",fd);
510
511 for (i=0; i<nl; i++)
512 {
513 if (DumpRhs(fd, (idhdl) &(l->m[i])) == EOF) return EOF;
514 fputs(",",fd);
515 }
516 if (nl > 0)
517 {
518 if (DumpRhs(fd, (idhdl) &(l->m[nl])) == EOF) return EOF;
519 }
520 fputs(")",fd);
521 }
522 else if (type_id == STRING_CMD)
523 {
524 char *pstr = IDSTRING(h);
525 fputc('"', fd);
526 while (*pstr != '\0')
527 {
528 if (*pstr == '"' || *pstr == '\\') fputc('\\', fd);
529 fputc(*pstr, fd);
530 pstr++;
531 }
532 fputc('"', fd);
533 }
534 else if (type_id == PROC_CMD)
535 {
536 procinfov pi = IDPROC(h);
537 if (pi->language == LANG_SINGULAR)
538 {
539 /* pi-Libname==NULL */
540 char *pstr = pi->data.s.body;
541 fputc('"', fd);
542 while (*pstr != '\0')
543 {
544 if (*pstr == '"' || *pstr == '\\') fputc('\\', fd);
545 fputc(*pstr, fd);
546 pstr++;
547 }
548 fputc('"', fd);
549 }
550 else fputs("(null)", fd);
551 }
552 else
553 {
554 char *rhs = h->String();
555
556 if (rhs == NULL) return EOF;
557
558 BOOLEAN need_klammer=FALSE;
559 if (type_id == INTVEC_CMD) { fputs("intvec(",fd);need_klammer=TRUE; }
560 else if (type_id == IDEAL_CMD) { fputs("ideal(",fd);need_klammer=TRUE; }
561 else if ((type_id == MODUL_CMD)||(type_id == SMATRIX_CMD))
562 { fputs("module(",fd);need_klammer=TRUE; }
563 else if (type_id == BIGINT_CMD) { fputs("bigint(",fd);need_klammer=TRUE; }
564
565 if (fputs(rhs,fd) == EOF) return EOF;
566 omFree(rhs);
567
568 if ((type_id == RING_CMD) &&
569 IDRING(h)->cf->type==n_algExt)
570 {
571 StringSetS("");
572 p_Write(IDRING(h)->cf->extRing->qideal->m[0],IDRING(h)->cf->extRing);
573 rhs = StringEndS();
574 if (fprintf(fd, "; minpoly = %s", rhs) == EOF) { omFree(rhs); return EOF;}
575 omFree(rhs);
576 }
577 else if (need_klammer) fputc(')',fd);
578 }
579 return 1;
580 }
581
slGetDumpAscii(si_link l)582 BOOLEAN slGetDumpAscii(si_link l)
583 {
584 if (l->name[0] == '\0')
585 {
586 WerrorS("getdump: Can not get dump from stdin");
587 return TRUE;
588 }
589 else
590 {
591 BOOLEAN status = newFile(l->name);
592 if (status)
593 return TRUE;
594
595 int old_echo=si_echo;
596 si_echo=0;
597
598 status=yyparse();
599
600 si_echo=old_echo;
601
602 if (status)
603 return TRUE;
604 else
605 {
606 // lets reset the file pointer to the end to reflect that
607 // we are finished with reading
608 FILE *f = (FILE *) l->data;
609 fseek(f, 0L, SEEK_END);
610 return FALSE;
611 }
612 }
613 }
614
615
slStandardInit()616 void slStandardInit()
617 {
618 si_link_extension s;
619 si_link_root=(si_link_extension)omAlloc0Bin(s_si_link_extension_bin);
620 si_link_root->Open=slOpenAscii;
621 si_link_root->Close=slCloseAscii;
622 si_link_root->Kill=NULL;
623 si_link_root->Read=slReadAscii;
624 si_link_root->Read2=slReadAscii2;
625 si_link_root->Write=slWriteAscii;
626 si_link_root->Dump=slDumpAscii;
627 si_link_root->GetDump=slGetDumpAscii;
628 si_link_root->Status=slStatusAscii;
629 si_link_root->type="ASCII";
630 s = si_link_root;
631 s->next = NULL;
632 }
633