source: git/Singular/fevoices.cc @ 121d2ae

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