source: git/Singular/fevoices.cc @ 1085d4

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