source: git/Singular/fevoices.cc @ 9d1e4c9

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