fevoices.cc
Go to the documentation of this file.
1 /****************************************
2 * Computer Algebra System SINGULAR *
3 ****************************************/
4 /*
5 * ABSTRACT: i/o system
6 */
7 #include <kernel/mod2.h>
8 
9 /* I need myfread in standalone_parser */
10 #ifndef STANDALONE_PARSER
11 
12 #include <omalloc/omalloc.h>
13 #include <misc/options.h>
14 #include <reporter/reporter.h>
16 #include <Singular/fevoices.h>
17 #include <Singular/subexpr.h>
18 #include <Singular/ipshell.h>
19 #include <Singular/sdb.h>
20 
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <misc/mylimits.h>
24 #include <stdarg.h>
25 #include <sys/stat.h>
26 #include <ctype.h>
27 #include <unistd.h>
28 
29 #ifdef HAVE_PWD_H
30 #include <pwd.h>
31 #endif
32 
33 #define fePutChar(c) fputc((unsigned char)(c),stdout)
34 /*0 implementation */
35 
36 
37 char fe_promptstr[] =" ";
39 
40 // output/print buffer:
41 #define INITIAL_PRINT_BUFFER 24*1024L
42 // line buffer for reading:
43 // minimal value for MAX_FILE_BUFFER: 4*4096 - see Tst/Long/gcd0_l.tst
44 // this is an upper limit for the size of monomials/numbers read via the interpreter
45 #define MAX_FILE_BUFFER 4*4096
46 // static long feBufferLength=INITIAL_PRINT_BUFFER;
47 static char * feBuffer=(char *)omAlloc(INITIAL_PRINT_BUFFER);
48 
49 /**************************************************************************
50 * handling of 'voices'
51 **************************************************************************/
52 
53 extern int blocknest; /* scaner.l internal */
54 
55 int yy_noeof=0; // the scanner "state"
56 int yy_blocklineno; // to get the lineno of the block start from scanner
58 // FILE *feFilePending; /*temp. storage for grammar.y */
59 
60 //static const char * BT_name[]={"BT_none","BT_break","BT_proc","BT_example",
61 // "BT_file","BT_execute","BT_if","BT_else"};
62 /*2
63 * the name of the current 'Voice': the procname (or filename)
64 */
65 const char * sNoName_fe="_";
66 const char * VoiceName()
67 {
68  if ((currentVoice!=NULL)
69  && (currentVoice->filename!=NULL))
70  return currentVoice->filename;
71  return sNoName_fe;
72 }
73 
74 /*2
75 * the calling chain of Voices
76 */
78 {
80  while (p->prev!=NULL)
81  {
82  p=p->prev;
83  char *s=p->filename;
84  if (s==NULL)
85  PrintS("-- called from ? --\n");
86  else
87  Print("-- called from %s --\n",s);
88  }
89 }
90 
91 /*2
92 * init a new voice similar to the current
93 */
95 {
96  Voice *p=new Voice;
97  // OB: ???
98  // Hmm... when Singular is used as batch file
99  // then this voice is never freed
101  if (currentVoice != NULL)
102  {
103  currentVoice->curr_lineno=yylineno;
104  currentVoice->next=p;
105  }
106  p->prev=currentVoice;
107  currentVoice=p;
108  //Print("Next:");
109 }
110 
112 {
113  switch(typ)
114  {
115  case BT_proc:
116  case BT_example:
117  case BT_file:
118  return typ;
119  default:
120  if (prev==NULL) return (feBufferTypes)0;
121  return prev->Typ();
122  }
123 }
124 
125 /*2
126 * start the file 'fname' (STDIN is stdin) as a new voice (cf.VFile)
127 * return FALSE on success, TRUE if an error occurs (file cannot be opened)
128 */
129 BOOLEAN newFile(char *fname,FILE* f)
130 {
131  currentVoice->Next();
132  //Print(":File%d(%s):%s(%x)\n",
133  // currentVoice->typ,BT_name[currentVoice->typ],fname,currentVoice);
134  currentVoice->filename = omStrDup(fname);
135  omMarkAsStaticAddr(currentVoice->filename);
136  if (strcmp(fname,"STDIN") == 0)
137  {
138  currentVoice->files = stdin;
139  currentVoice->sw = BI_stdin;
140  currentVoice->start_lineno = 1;
141  }
142  else
143  {
144  currentVoice->sw = BI_file; /* needed by exitVoice below */
145  if (f!=NULL)
146  currentVoice->files = f;
147  else
148  {
149  currentVoice->files = feFopen(fname,"r",NULL,TRUE);
150  if (currentVoice->files==NULL)
151  {
152  exitVoice();
153  return TRUE;
154  }
155  }
156  currentVoice->start_lineno = 0;
157  }
158  yylineno=currentVoice->start_lineno;
159  //Voice *p=currentVoice;
160  //Print("-----------------\ncurr:");
161  //do
162  //{
163  //Print("voice fn:%s\n",p->filename);
164  //p=p->prev;
165  //}
166  //while (p!=NULL);
167  //Print("----------------\n");
168  return FALSE;
169 }
170 
171 void newBuffer(char* s, feBufferTypes t, procinfo* pi, int lineno)
172 {
173  currentVoice->Next();
174  //Print(":Buffer%d(%s):%s(%x)\n",
175  // t,BT_name[t],pname,currentVoice);
176  if (pi!=NULL)
177  {
178  long l=strlen(pi->procname);
179  if (pi->libname!=NULL) l+=strlen(pi->libname);
180  currentVoice->filename = (char *)omAlloc(l+3);
181  *currentVoice->filename='\0';
182  if (pi->libname!=NULL) strcat(currentVoice->filename,pi->libname);
183  strcat(currentVoice->filename,"::");
184  strcat(currentVoice->filename,pi->procname);
185  currentVoice->pi = pi;
186  }
187  else
188  {
189  currentVoice->filename = omStrDup(currentVoice->prev->filename);
190  currentVoice->pi = currentVoice->prev->pi;
191  }
192  currentVoice->buffer = s;
193  currentVoice->sw = BI_buffer;
194  currentVoice->typ = t;
195  switch (t)
196  {
197  case BT_execute:
198  yylineno-=2;
199  break;
200  case BT_proc:
201  case BT_example:
202  currentVoice->oldb=myynewbuffer();
203  yylineno = lineno+1;
204  break;
205  case BT_if:
206  case BT_else:
207  case BT_break:
208  yylineno = yy_blocklineno-1;
209  break;
210  //case BT_file:
211  default:
212  yylineno = 1;
213  break;
214  }
215  //Print("start body (%s) at line %d\n",BT_name[t],yylineno);
216  currentVoice->start_lineno = yylineno;
217  //printf("start buffer typ %d\n",t);
218  //Voice *p=currentVoice;
219  //Print("-----------------\ncurr:");
220  //do
221  //{
222  //Print("voice fn:%s\n",p->filename);
223  //p=p->prev;
224  //}
225  //while (p!=NULL);
226  //Print("----------------\n");
227 }
228 
229 /*2
230 * exit Buffer of type 'typ':
231 * returns 1 if buffer type could not be found
232 */
234 {
235  //printf("exitBuffer: %d(%s),(%x)\n",
236  // typ,BT_name[typ], currentVoice);
237  //Voice *p=currentVoice;
238  //Print("-----------------\ncurr:");
239  //do
240  //{
241  //Print("voice fn:%s\n",p->filename);
242  //p=p->prev;
243  //}
244  //while (p!=NULL);
245  //Print("----------------\n");
246  if (typ == BT_break) // valid inside for, while. may skip if, else
247  {
248  /*4 first check for valid buffer type, skip if/else*/
250  loop
251  {
252  if ((p->typ != BT_if)
253  &&(p->typ != BT_else))
254  {
255  if (p->typ == BT_break /*typ*/)
256  {
257  while (p != currentVoice)
258  {
259  exitVoice();
260  }
261  exitVoice();
262  return FALSE;
263  }
264  else return TRUE;
265  }
266  if (p->prev==NULL) break;
267  p=p->prev;
268  }
269  /*4 break not inside a for/while: return an error*/
270  if (/*typ*/ BT_break != currentVoice->typ) return 1;
271  return exitVoice();
272  }
273 
274  if ((typ == BT_proc)
275  || (typ == BT_example))
276  {
278  loop
279  {
280  if ((p->typ == BT_proc)
281  || (p->typ == BT_example))
282  {
283  while (p != currentVoice)
284  {
285  exitVoice();
286  }
287  exitVoice();
288  return FALSE;
289  }
290  if (p->prev==NULL) break;
291  p=p->prev;
292  }
293  }
294  /*4 return not inside a proc: return an error*/
295  return TRUE;
296 }
297 
298 /*2
299 * jump to the beginning of a buffer
300 */
302 {
303  //printf("contBuffer: %d(%s),(%x)\n",
304  // typ,BT_name[typ], currentVoice);
305  if (typ == BT_break) // valid inside for, while. may skip if, else
306  {
307  // first check for valid buffer type
309  loop
310  {
311  if ((p->typ != BT_if)
312  &&(p->typ != BT_else))
313  {
314  if (p->typ == BT_break /*typ*/)
315  {
316  while (p != currentVoice)
317  {
318  exitVoice();
319  }
320  yylineno = currentVoice->start_lineno;
321  currentVoice->fptr=0;
322  return FALSE;
323  }
324  else return TRUE;
325  }
326  if (p->prev==NULL) break;
327  p=p->prev;
328  }
329  }
330  return TRUE;
331 }
332 
333 /*2
334 * leave a voice: kill local variables
335 * setup everything from the previous level
336 * return 1 if leaving the top level, 0 otherwise
337 */
339 {
340  //printf("exitVoice: %d(%s),(%x)\n",
341  // currentVoice->typ,BT_name[currentVoice->typ], currentVoice);
342  //{
343  //Voice *p=currentVoice;
344  //Print("-----------------\ncurr:");
345  //do
346  //{
347  //Print("voice fn:%s\n",p->filename);
348  //p=p->prev;
349  //}
350  //while (p!=NULL);
351  //Print("----------------\n");
352  //}
353  if (currentVoice!=NULL)
354  {
355  if (currentVoice->oldb!=NULL)
356  {
357  myyoldbuffer(currentVoice->oldb);
358  currentVoice->oldb=NULL;
359  }
360  if ((currentVoice->prev==NULL)&&(currentVoice->sw==BI_file))
361  {
362  currentVoice->prev=feInitStdin(currentVoice);
363  }
364  if (currentVoice->prev!=NULL)
365  {
366  //printf("exitVoice typ %d(%s)\n",
367  // currentVoice->typ,BT_name[currentVoice->typ]);
368  if (currentVoice->typ==BT_if)
369  {
370  currentVoice->prev->ifsw=2;
371  }
372  else
373  {
374  currentVoice->prev->ifsw=0;
375  }
376  if ((currentVoice->sw == BI_file)
377  && (currentVoice->files!=NULL))
378  {
379  fclose(currentVoice->files);
380  }
381  if (currentVoice->filename!=NULL)
382  {
383  omFree((ADDRESS)currentVoice->filename);
384  currentVoice->filename=NULL;
385  }
386  if (currentVoice->buffer!=NULL)
387  {
388  omFree((ADDRESS)currentVoice->buffer);
389  currentVoice->buffer=NULL;
390  }
391  yylineno=currentVoice->prev->curr_lineno;
392  currentVoice->prev->next=NULL;
393  }
394  Voice *p=currentVoice->prev;
395  delete currentVoice;
396  currentVoice=p;
397  }
398  return currentVoice==NULL;
399 }
400 
401 /*2
402 * set prompt_char
403 * only called with currentVoice->sw == BI_stdin
404 */
405 static void feShowPrompt(void)
406 {
408 }
409 
410 /*2
411 * print echo (si_echo or TRACE), set my_yylinebuf
412 */
413 static int fePrintEcho(char *anf, char */*b*/)
414 {
415  char *ss=strrchr(anf,'\n');
416  int len_s;
417  if (ss==NULL)
418  {
419  len_s=strlen(anf);
420  }
421  else
422  {
423  len_s=ss-anf+1;
424  }
425  // my_yylinebuf:
426  int mrc=si_min(len_s,79)-1;
427  strcpy(my_yylinebuf,anf+(len_s-1)-mrc);
428  if (my_yylinebuf[mrc] == '\n') my_yylinebuf[mrc] = '\0';
429  mrc--;
430  // handle echo:
431  if (((si_echo>myynest)
432  && ((currentVoice->typ==BT_proc)
433  || (currentVoice->typ==BT_example)
434  || (currentVoice->typ==BT_file)
435  || (currentVoice->typ==BT_none)
436  )
437  && (strncmp(anf,";return();",10)!=0)
438  )
441  {
442  if (currentVoice->typ!=BT_example)
443  {
444  if (currentVoice->filename==NULL)
445  Print("(none) %3d%c ",yylineno,prompt_char);
446  else
447  Print("%s %3d%c ",currentVoice->filename,yylineno,prompt_char);
448  }
449  {
450  fwrite(anf,1,len_s,stdout);
451  mflush();
452  }
453  if (traceit&TRACE_SHOW_LINE)
454  {
455  while(fgetc(stdin)!='\n');
456  }
457  }
458  else if (traceit&TRACE_SHOW_LINENO)
459  {
460  Print("{%d}",yylineno);
461  mflush();
462  }
463  else if (traceit&TRACE_PROFILING)
464  {
465  if (File_Profiling==NULL)
466  File_Profiling=fopen("smon.out","a");
467  if (File_Profiling==NULL)
468  traceit &= (~TRACE_PROFILING);
469  else
470  {
471  if (currentVoice->filename==NULL)
472  fprintf(File_Profiling,"(none) %d\n",yylineno);
473  else
474  fprintf(File_Profiling,"%s %d\n",currentVoice->filename,yylineno);
475  }
476  }
477 #ifdef HAVE_SDB
478  if ((blocknest==0)
479  && (currentVoice->pi!=NULL)
480  && (currentVoice->pi->trace_flag!=0))
481  {
482  sdb(currentVoice, anf, len_s);
483  }
484 #endif
485  prompt_char = '.';
486  return len_s;
487 }
488 
489 int feReadLine(char* b, int l)
490 {
491  char *s=NULL;
492  int offset = 0; /* will not be used if s==NULL*/
493  // try to read from the buffer into b, max l chars
494  if (currentVoice!=NULL)
495  {
496  if((currentVoice->buffer!=NULL)
497  && (currentVoice->buffer[currentVoice->fptr]!='\0'))
498  {
499  NewBuff:
500  register int i=0;
501  long startfptr=currentVoice->fptr;
502  long tmp_ptr=currentVoice->fptr;
503  l--;
504  loop
505  {
506  register char c=
507  b[i]=currentVoice->buffer[tmp_ptr/*currentVoice->fptr*/];
508  i++;
509  if (yy_noeof==noeof_block)
510  {
511  if (c<' ') yylineno++;
512  else if (c=='}') break;
513  }
514  else
515  {
516  if ((c<' ') ||
517  (c==';') ||
518  (c==')')
519  )
520  break;
521  }
522  if (i>=l) break;
523  tmp_ptr++;/*currentVoice->fptr++;*/
524  if(currentVoice->buffer[tmp_ptr/*currentVoice->fptr*/]=='\0') break;
525  }
526  currentVoice->fptr=tmp_ptr;
527  b[i]='\0';
528  if (currentVoice->sw==BI_buffer)
529  {
530  if (startfptr==0)
531  {
532  char *anf=currentVoice->buffer;
533  const char *ss=strchr(anf,'\n');
534  long len;
535  if (ss==NULL) len=strlen(anf);
536  else len=ss-anf;
537  char *s=(char *)omAlloc(len+2);
538  strncpy(s,anf,len+2);
539  s[len+1]='\0';
540  fePrintEcho(s,b);
541  omFree((ADDRESS)s);
542  }
543  else if (/*(startfptr>0) &&*/
544  (currentVoice->buffer[startfptr-1]=='\n'))
545  {
546  char *anf=currentVoice->buffer+startfptr;
547  const char *ss=strchr(anf,'\n');
548  long len;
549  if (ss==NULL) len=strlen(anf);
550  else len=ss-anf;
551  char *s=(char *)omAlloc(len+2);
552  strncpy(s,anf,len+2);
553  s[len+1]='\0';
554  yylineno++;
555  fePrintEcho(s,b);
556  omFree((ADDRESS)s);
557  }
558  }
559  currentVoice->fptr++;
560  return i;
561  }
562  // no buffer there or e-o-buffer or eoln:
563  if (currentVoice->sw!=BI_buffer)
564  {
565  currentVoice->fptr=0;
566  if (currentVoice->buffer==NULL)
567  {
568  currentVoice->buffer=(char *)omAlloc(MAX_FILE_BUFFER-sizeof(ADDRESS));
569  omMarkAsStaticAddr(currentVoice->buffer);
570  }
571  }
572  offset=0;
573  NewRead:
574  yylineno++;
575  if (currentVoice->sw==BI_stdin)
576  {
577  feShowPrompt();
579  &(currentVoice->buffer[offset]),
580  omSizeOfAddr(currentVoice->buffer)-1-offset);
581  //int i=0;
582  //if (s!=NULL)
583  // while((s[i]!='\0') /*&& (i<MAX_FILE_BUFFER)*/) {s[i] &= (char)127;i++;}
584  }
585  else if (currentVoice->sw==BI_file)
586  {
587  s=fgets(currentVoice->buffer+offset,(MAX_FILE_BUFFER-1-sizeof(ADDRESS))-offset,
588  currentVoice->files);
589  }
590  //else /* BI_buffer */ s==NULL => return 0
591  // done by the default return
592  }
593  if (s!=NULL)
594  {
595  // handle prot:
596  if (feProt&SI_PROT_I)
597  {
598  fputs(s,feProtFile);
599  }
600  int rc=fePrintEcho(s,b)+1;
601  //s[strlen(s)+1]='\0'; add an second \0 at the end of the string
602  s[rc]='\0';
603  // handel \\ :
604  rc-=3;
605  if ((s[rc]=='\\')&&(currentVoice->sw!=BI_buffer))
606  {
607  s[rc]='\0';
608  offset+=rc;
609  if (offset<(int)omSizeOfAddr(currentVoice->buffer)) goto NewRead;
610  }
611  goto NewBuff;
612  }
613  /* else if (s==NULL) */
614  {
615  const char *err;
616  switch(yy_noeof)
617  {
618  case noeof_brace:
619  case noeof_block:
620  err="{...}";
621  break;
622  case noeof_asstring:
623  err="till `.`";
624  break;
625  case noeof_string:
626  err="string";
627  break;
628  case noeof_bracket:
629  err="(...)";
630  break;
631  case noeof_procname:
632  err="proc";
633  break;
634  case noeof_comment:
635  err="/*...*/";
636  break;
637  default:
638  return 0;
639  }
640  Werror("premature end of file while reading %s",err);
641  return 0;
642  }
643 }
644 
645 /*2
646 * init all data structures
647 */
648 #ifndef STDIN_FILENO
649 #define STDIN_FILENO 0
650 #endif
652 {
653  Voice *p = new Voice;
654  p->files = stdin;
655  p->sw = (isatty(STDIN_FILENO)) ? BI_stdin : BI_file;
656  if ((pp!=NULL) && (pp->files==stdin))
657  {
658  p->files=freopen("/dev/tty","r",stdin);
659  //stdin=p->files;
660  p->sw = BI_stdin;
661  }
662  p->filename = omStrDup("STDIN");
663  p->start_lineno = 1;
666  return p;
667 }
668 
669 
670 #else /* ! STANDALONE_PARSER */
671 #include <stdio.h>
672 
673 #endif
674 
char fe_promptstr[]
Definition: fevoices.cc:37
long fptr
Definition: fevoices.h:69
FILE * feProtFile
Definition: reporter.cc:57
void VoiceBackTrack()
Definition: fevoices.cc:77
int yy_noeof
Definition: fevoices.cc:55
const CanonicalForm int s
Definition: facAbsFact.cc:55
#define TRACE_SHOW_LINENO
Definition: reporter.h:28
char *(* fe_fgets_stdin)(const char *pr, char *s, int size)
Definition: feread.cc:33
int yylineno
Definition: febase.cc:45
#define Print
Definition: emacs.cc:83
char * buffer
Definition: fevoices.h:68
static void feShowPrompt(void)
Definition: fevoices.cc:405
loop
Definition: myNF.cc:98
static int si_min(const int a, const int b)
Definition: auxiliary.h:167
void Next()
Definition: fevoices.cc:94
#define FALSE
Definition: auxiliary.h:140
size_t omSizeOfAddr(const void *addr)
Definition: omAllocSystem.c:97
return P p
Definition: myNF.cc:203
feBufferTypes Typ()
Definition: fevoices.cc:111
char * filename
Definition: fevoices.h:62
char prompt_char
Definition: febase.cc:44
void * myynewbuffer()
Definition: scanner.cc:2319
#define TRUE
Definition: auxiliary.h:144
int blocknest
Definition: scanner.cc:581
void * ADDRESS
Definition: auxiliary.h:161
FILE * File_Profiling
Definition: fevoices.cc:38
Definition: fevoices.h:57
int traceit
Definition: febase.cc:47
Voice * next
Definition: fevoices.h:60
int curr_lineno
Definition: fevoices.h:72
#define omAlloc(size)
Definition: omAllocDecl.h:210
BOOLEAN exitBuffer(feBufferTypes typ)
Definition: fevoices.cc:233
poly pp
Definition: myNF.cc:296
int feProt
Definition: reporter.cc:56
void sdb(Voice *currentVoice, const char *currLine, int len)
Definition: sdb.cc:201
#define SI_PROT_I
Definition: reporter.h:50
int start_lineno
Definition: fevoices.h:71
#define mflush()
Definition: reporter.h:55
char ifsw
Definition: fevoices.h:76
char * procname
Definition: subexpr.h:56
Definition: fevoices.h:24
int myynest
Definition: febase.cc:46
char my_yylinebuf[80]
Definition: febase.cc:48
static char * feBuffer
Definition: fevoices.cc:47
char * libname
Definition: subexpr.h:55
Voice * feInitStdin(Voice *pp)
Definition: fevoices.cc:651
#define TRACE_SHOW_LINE
Definition: reporter.h:30
procinfo * pi
Definition: fevoices.h:63
#define omFree(addr)
Definition: omAllocDecl.h:261
static int fePrintEcho(char *anf, char *)
Definition: fevoices.cc:413
#define STDIN_FILENO
Definition: fevoices.cc:649
BOOLEAN exitVoice()
Definition: fevoices.cc:338
FILE * feFopen(const char *path, const char *mode, char *where, short useWerror, short path_only)
Definition: feFopen.cc:46
FILE * f
Definition: checklibs.c:7
int i
Definition: cfEzgcd.cc:123
void PrintS(const char *s)
Definition: reporter.cc:294
feBufferTypes typ
Definition: fevoices.h:81
#define INITIAL_PRINT_BUFFER
Definition: fevoices.cc:41
const char * VoiceName()
Definition: fevoices.cc:66
Voice * prev
Definition: fevoices.h:61
#define TRACE_SHOW_LINE1
Definition: reporter.h:35
#define pi
Definition: libparse.cc:1143
void * oldb
Definition: fevoices.h:64
feBufferTypes
Definition: fevoices.h:16
void myyoldbuffer(void *oldb)
Definition: scanner.cc:2326
int yy_blocklineno
Definition: fevoices.cc:56
#define NULL
Definition: omList.c:10
#define MAX_FILE_BUFFER
Definition: fevoices.cc:45
Voice * currentVoice
Definition: fevoices.cc:57
#define TRACE_PROFILING
Definition: reporter.h:47
FILE * files
Definition: fevoices.h:66
const char * sNoName_fe
Definition: fevoices.cc:65
void newBuffer(char *s, feBufferTypes t, procinfo *pi, int lineno)
Definition: fevoices.cc:171
BOOLEAN newFile(char *fname, FILE *f)
Definition: fevoices.cc:129
void omMarkAsStaticAddr(void *addr)
int feReadLine(char *b, int l)
Definition: fevoices.cc:489
feBufferInputs sw
Definition: fevoices.h:73
Voice()
Definition: fevoices.h:83
int offset
Definition: libparse.cc:1091
int BOOLEAN
Definition: auxiliary.h:131
const poly b
Definition: syzextra.cc:213
char trace_flag
Definition: subexpr.h:61
void Werror(const char *fmt,...)
Definition: reporter.cc:199
int l
Definition: cfEzgcd.cc:94
int si_echo
Definition: febase.cc:41
BOOLEAN contBuffer(feBufferTypes typ)
Definition: fevoices.cc:301
#define omStrDup(s)
Definition: omAllocDecl.h:263