source: git/Singular/fevoices.cc @ abb12f

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