source: git/Singular/fevoices.cc @ 584b82

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