source: git/Singular/fevoices.cc @ d37ac6

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