source: git/Singular/fevoices.cc @ 291c20

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