source: git/kernel/febase.cc @ bc669c

fieker-DuValspielwiese
Last change on this file since bc669c was 6c4db17, checked in by Hans Schönemann <hannes@…>, 14 years ago
option(qringNF), track 149 git-svn-id: file:///usr/local/Singular/svn/trunk@12513 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 26.5 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 "mod2.h"
12
13#include <stdlib.h>
14#include <stdio.h>
15#include <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 "febase.h"
26#include "omalloc.h"
27#include "dError.h"
28#include "options.h"
29
30#define fePutChar(c) fputc((unsigned char)(c),stdout)
31/*0 implementation */
32
33char fe_promptstr[] ="  ";
34
35// output/print buffer:
36#define INITIAL_PRINT_BUFFER 24*1024L
37// line buffer for reading:
38// minimal value for MAX_FILE_BUFFER: 4*4096 - see Tst/Long/gcd0_l.tst
39// this is an upper limit for the size of monomials/numbers read via the interpreter
40#define MAX_FILE_BUFFER 4*4096
41static long feBufferLength=INITIAL_PRINT_BUFFER;
42static char * feBuffer=(char *)omAlloc(INITIAL_PRINT_BUFFER);
43
44int     si_echo = 0;
45int     printlevel = 0;
46int     pagelength = 24;
47int     colmax = 80;
48char    prompt_char = '>'; /*1 either '>' or '.'*/
49extern "C" {
50BITSET  test=(BITSET)0;
51BITSET  verbose = Sy_bit(V_QUIET)
52                  //| Sy_bit(V_QRING) // not default, as speed drops by 10 %
53                  | Sy_bit(V_REDEFINE)
54                  | Sy_bit(V_LOAD_LIB)
55                  | Sy_bit(V_SHOW_USE)
56                  | Sy_bit(V_PROMPT)
57/*                  | Sy_bit(V_DEBUG_MEM) */
58;}
59BOOLEAN errorreported = FALSE;
60char *  feErrors=NULL;
61int     feErrorsLen=0;
62BOOLEAN feWarn = TRUE;
63BOOLEAN feOut = TRUE;
64
65const char feNotImplemented[]="not implemented";
66
67int feProt = FALSE;
68FILE*   feProtFile;
69BOOLEAN tclmode=FALSE;
70/* TCL-Protocoll (Singular -x): <char type>:<int length>:<string> \n
71*  E:l:s  error
72*  W:l:s  warning
73*  N:l:s  stdout
74*  Q:0:   quit
75*  P:l:   prompt > (ring defined)
76*  U:l:   prompt > (no ring defined)
77*  P:l:   prompt .
78*  R:l:<ring-name> ring change
79*  L:l:<lib name> library loaded
80*  O:l:<list of options(space seperated)> option change
81*  M:l:<mem-usage> output from "option(mem)"
82*/
83
84
85/**************************************************************************
86* handling of 'voices'
87**************************************************************************/
88
89extern int blocknest; /* scaner.l internal */
90
91int    yy_noeof=0;     // the scanner "state"
92int    yy_blocklineno; // to get the lineno of the block start from scanner
93Voice  *currentVoice = NULL;
94FILE   *feFilePending; /*temp. storage for grammar.y */
95
96static const char * BT_name[]={"BT_none","BT_break","BT_proc","BT_example",
97                               "BT_file","BT_execute","BT_if","BT_else"};
98/*2
99* the name of the current 'Voice': the procname (or filename)
100*/
101const char * sNoName_fe="_";
102const char * VoiceName()
103{
104  if ((currentVoice!=NULL)
105  && (currentVoice->filename!=NULL))
106    return currentVoice->filename;
107  return sNoName_fe;
108}
109
110/*2
111* the calling chain of Voices
112*/
113void VoiceBackTrack()
114{
115  Voice *p=currentVoice;
116  while (p->prev!=NULL)
117  {
118    p=p->prev;
119    char *s=p->filename;
120    if (s==NULL)
121      PrintS("-- called from ? --\n");
122    else
123      Print("-- called from %s --\n",s);
124  }
125}
126
127/*2
128* init a new voice similiar to the current
129*/
130void Voice::Next()
131{
132  Voice *p=new Voice;
133  // OB: ???
134  // Hmm... when Singular is used as batch file
135  // then this voice is never freed
136  omMarkAsStaticAddr(p);
137  if (currentVoice != NULL)
138  {
139    currentVoice->curr_lineno=yylineno;
140    currentVoice->next=p;
141  }
142  p->prev=currentVoice;
143  currentVoice=p;
144  //Print("Next:");
145}
146
147feBufferTypes Voice::Typ()
148{
149  switch(typ)
150  {
151    case BT_proc:
152    case BT_example:
153    case BT_file:
154      return typ;
155    default:
156      if (prev==NULL) return (feBufferTypes)0;
157      return prev->Typ();
158  }
159}
160
161/*2
162* start the file 'fname' (STDIN is stdin) as a new voice (cf.VFile)
163* return FALSE on success, TRUE if an error occurs (file cannot be opened)
164*/
165BOOLEAN newFile(char *fname,FILE* f)
166{
167  currentVoice->Next();
168  //Print(":File%d(%s):%s(%x)\n",
169  //  currentVoice->typ,BT_name[currentVoice->typ],fname,currentVoice);
170  currentVoice->filename   = omStrDup(fname);
171  omMarkAsStaticAddr(currentVoice->filename);
172  if (strcmp(fname,"STDIN") == 0)
173  {
174    currentVoice->files = stdin;
175    currentVoice->sw = BI_stdin;
176    currentVoice->start_lineno = 1;
177  }
178  else
179  {
180    currentVoice->sw = BI_file; /* needed by exitVoice below */
181    if (f!=NULL)
182      currentVoice->files = f;
183    else
184    {
185      currentVoice->files = feFopen(fname,"r",NULL,TRUE);
186      if (currentVoice->files==NULL)
187      {
188        exitVoice();
189        return TRUE;
190      }
191    }
192    currentVoice->start_lineno = 0;
193  }
194  yylineno=currentVoice->start_lineno;
195  //Voice *p=currentVoice;
196  //Print("-----------------\ncurr:");
197  //do
198  //{
199  //Print("voice fn:%s\n",p->filename);
200  //p=p->prev;
201  //}
202  //while (p!=NULL);
203  //Print("----------------\n");
204  return FALSE;
205}
206
207void newBuffer(char* s, feBufferTypes t, procinfo* pi, int lineno)
208{
209  currentVoice->Next();
210  //Print(":Buffer%d(%s):%s(%x)\n",
211  //  t,BT_name[t],pname,currentVoice);
212  if (pi!=NULL)
213  {
214    long l=strlen(pi->procname);
215    if (pi->libname!=NULL) l+=strlen(pi->libname);
216    currentVoice->filename = (char *)omAlloc(l+3);
217    *currentVoice->filename='\0';
218    if (pi->libname!=NULL) strcat(currentVoice->filename,pi->libname);
219    strcat(currentVoice->filename,"::");
220    strcat(currentVoice->filename,pi->procname);
221    currentVoice->pi       = pi;
222  }
223  else
224  {
225    currentVoice->filename = omStrDup(currentVoice->prev->filename);
226    currentVoice->pi       = currentVoice->prev->pi;
227  }
228  currentVoice->buffer   = s;
229  currentVoice->sw       = BI_buffer;
230  currentVoice->typ      = t;
231  switch (t)
232  {
233    case BT_execute:
234                     yylineno-=2;
235                     break;
236    case BT_proc:
237    case BT_example:
238                     currentVoice->oldb=myynewbuffer();
239                     yylineno = lineno+1;
240                     break;
241    case BT_if:
242    case BT_else:
243    case BT_break:
244                     yylineno = yy_blocklineno-1;
245                     break;
246    //case BT_file:
247    default:
248                     yylineno = 1;
249                     break;
250  }
251  //Print("start body (%s) at line %d\n",BT_name[t],yylineno);
252  currentVoice->start_lineno = yylineno;
253  //printf("start buffer typ %d\n",t);
254  //Voice *p=currentVoice;
255  //Print("-----------------\ncurr:");
256  //do
257  //{
258  //Print("voice fn:%s\n",p->filename);
259  //p=p->prev;
260  //}
261  //while (p!=NULL);
262  //Print("----------------\n");
263}
264
265/*2
266* exit Buffer of type 'typ':
267* returns 1 if buffer type could not be found
268*/
269BOOLEAN exitBuffer(feBufferTypes typ)
270{
271  //printf("exitBuffer: %d(%s),(%x)\n",
272  //  typ,BT_name[typ], currentVoice);
273  //Voice *p=currentVoice;
274  //Print("-----------------\ncurr:");
275  //do
276  //{
277  //Print("voice fn:%s\n",p->filename);
278  //p=p->prev;
279  //}
280  //while (p!=NULL);
281  //Print("----------------\n");
282  if (typ == BT_break)  // valid inside for, while. may skip if, else
283  {
284    /*4 first check for valid buffer type, skip if/else*/
285    Voice *p=currentVoice;
286    loop
287    {
288      if ((p->typ != BT_if)
289      &&(p->typ != BT_else))
290      {
291        if (p->typ == BT_break /*typ*/)
292        {
293          while (p != currentVoice)
294          {
295            exitVoice();
296          }
297          exitVoice();
298          return FALSE;
299        }
300        else return TRUE;
301      }
302      if (p->prev==NULL) break;
303      p=p->prev;
304    }
305    /*4 break not inside a for/while: return an error*/
306    if (/*typ*/ BT_break != currentVoice->typ) return 1;
307    return exitVoice();
308  }
309
310  if ((typ == BT_proc)
311  || (typ == BT_example))
312  {
313    Voice *p=currentVoice;
314    loop
315    {
316      if ((p->typ == BT_proc)
317      || (p->typ == BT_example))
318      {
319        while (p != currentVoice)
320        {
321          exitVoice();
322        }
323        exitVoice();
324        return FALSE;
325      }
326      if (p->prev==NULL) break;
327      p=p->prev;
328    }
329  }
330  /*4 return not inside a proc: return an error*/
331  return TRUE;
332}
333
334/*2
335* jump to the beginning of a buffer
336*/
337BOOLEAN contBuffer(feBufferTypes typ)
338{
339  //printf("contBuffer: %d(%s),(%x)\n",
340  //  typ,BT_name[typ], currentVoice);
341  if (typ == BT_break)  // valid inside for, while. may skip if, else
342  {
343    // first check for valid buffer type
344    Voice *p=currentVoice;
345    loop
346    {
347      if ((p->typ != BT_if)
348        &&(p->typ != BT_else))
349      {
350        if (p->typ == BT_break /*typ*/)
351        {
352          while (p != currentVoice)
353          {
354            exitVoice();
355          }
356          yylineno = currentVoice->start_lineno;
357          currentVoice->fptr=0;
358          return FALSE;
359        }
360        else return TRUE;
361      }
362      if (p->prev==NULL) break;
363      p=p->prev;
364    }
365  }
366  return TRUE;
367}
368
369/*2
370* leave a voice: kill local variables
371* setup everything from the previous level
372* return 1 if leaving the top level, 0 otherwise
373*/
374BOOLEAN exitVoice()
375{
376  //printf("exitVoice: %d(%s),(%x)\n",
377  //  currentVoice->typ,BT_name[currentVoice->typ], currentVoice);
378  //{
379  //Voice *p=currentVoice;
380  //Print("-----------------\ncurr:");
381  //do
382  //{
383  //Print("voice fn:%s\n",p->filename);
384  //p=p->prev;
385  //}
386  //while (p!=NULL);
387  //Print("----------------\n");
388  //}
389  if (currentVoice!=NULL)
390  {
391    if (currentVoice->oldb!=NULL)
392    {
393      myyoldbuffer(currentVoice->oldb);
394      currentVoice->oldb=NULL;
395    }
396    if ((currentVoice->prev==NULL)&&(currentVoice->sw==BI_file))
397    {
398      currentVoice->prev=feInitStdin(currentVoice);
399    }
400    if (currentVoice->prev!=NULL)
401    {
402      //printf("exitVoice typ %d(%s)\n",
403      //  currentVoice->typ,BT_name[currentVoice->typ]);
404      if (currentVoice->typ==BT_if)
405      {
406        currentVoice->prev->ifsw=2;
407      }
408      else
409      {
410        currentVoice->prev->ifsw=0;
411      }
412      if ((currentVoice->sw == BI_file)
413      && (currentVoice->files!=NULL))
414      {
415        fclose(currentVoice->files);
416      }
417      if (currentVoice->filename!=NULL)
418      {
419        omFree((ADDRESS)currentVoice->filename);
420        currentVoice->filename=NULL;
421      }
422      if (currentVoice->buffer!=NULL)
423      {
424        omFree((ADDRESS)currentVoice->buffer);
425        currentVoice->buffer=NULL;
426      }
427      yylineno=currentVoice->prev->curr_lineno;
428      currentVoice->prev->next=NULL;
429    }
430    Voice *p=currentVoice->prev;
431    delete currentVoice;
432    currentVoice=p;
433  }
434  return currentVoice==NULL;
435}
436
437/*2
438* set prompt_char
439* only called with currentVoice->sw == BI_stdin
440*/
441static void feShowPrompt(void)
442{
443  fe_promptstr[0]=prompt_char;
444}
445
446/*2
447* print echo (si_echo or TRACE), set my_yylinebuf
448*/
449static int fePrintEcho(char *anf, char *b)
450{
451  char *ss=strrchr(anf,'\n');
452  int len_s;
453  if (ss==NULL)
454  {
455    len_s=strlen(anf);
456  }
457  else
458  {
459    len_s=ss-anf+1;
460  }
461  // my_yylinebuf:
462  int mrc=si_min(len_s,79)-1;
463  strcpy(my_yylinebuf,anf+(len_s-1)-mrc);
464  if (my_yylinebuf[mrc] == '\n') my_yylinebuf[mrc] = '\0';
465  mrc--;
466  // handle echo:
467  if (((si_echo>myynest)
468    && ((currentVoice->typ==BT_proc)
469      || (currentVoice->typ==BT_example)
470      || (currentVoice->typ==BT_file)
471      || (currentVoice->typ==BT_none)
472    )
473    && (strncmp(anf,";return();",10)!=0)
474   )
475  || (traceit&TRACE_SHOW_LINE)
476  || (traceit&TRACE_SHOW_LINE1))
477  {
478    if (currentVoice->typ!=BT_example)
479    {
480      if (currentVoice->filename==NULL)
481        Print("(none) %3d%c ",yylineno,prompt_char);
482      else
483        Print("%s %3d%c ",currentVoice->filename,yylineno,prompt_char);
484     }
485    #ifdef HAVE_TCL
486    if(tclmode)
487    {
488      PrintTCL('N',len_s,anf);
489    }
490    else
491    #endif
492    {
493      fwrite(anf,1,len_s,stdout);
494      mflush();
495    }
496    if (traceit&TRACE_SHOW_LINE)
497    {
498      #ifdef HAVE_TCL
499      if(!tclmode)
500      #endif
501      while(fgetc(stdin)!='\n');
502    }
503  }
504  else if (traceit&TRACE_SHOW_LINENO)
505  {
506    Print("{%d}",yylineno);
507    mflush();
508  }
509#ifdef HAVE_SDB
510  if ((blocknest==0)
511  && (currentVoice->pi!=NULL)
512  && (currentVoice->pi->trace_flag!=0))
513  {
514    sdb(currentVoice, anf, len_s);
515  }
516#endif
517  prompt_char = '.';
518  return len_s;
519}
520
521int feReadLine(char* b, int l)
522{
523  char *s=NULL;
524  int offset = 0; /* will not be used if s==NULL*/
525  // try to read from the buffer into b, max l chars
526  if (currentVoice!=NULL)
527  {
528    if((currentVoice->buffer!=NULL)
529    && (currentVoice->buffer[currentVoice->fptr]!='\0'))
530    {
531  NewBuff:
532      register int i=0;
533      long startfptr=currentVoice->fptr;
534      long tmp_ptr=currentVoice->fptr;
535      l--;
536      loop
537      {
538        register char c=
539        b[i]=currentVoice->buffer[tmp_ptr/*currentVoice->fptr*/];
540        i++;
541        if (yy_noeof==noeof_block)
542        {
543          if (c<' ')  yylineno++;
544          else if (c=='}') break;
545        }
546        else
547        {
548          if ((c<' ') ||
549          (c==';') ||
550          (c==')')
551          )
552            break;
553        }
554        if (i>=l) break;
555        tmp_ptr++;/*currentVoice->fptr++;*/
556        if(currentVoice->buffer[tmp_ptr/*currentVoice->fptr*/]=='\0') break;
557      }
558      currentVoice->fptr=tmp_ptr;
559      b[i]='\0';
560      if (currentVoice->sw==BI_buffer)
561      {
562        if (startfptr==0)
563        {
564          char *anf=currentVoice->buffer;
565          const char *ss=strchr(anf,'\n');
566          long len;
567          if (ss==NULL) len=strlen(anf);
568          else          len=ss-anf;
569          char *s=(char *)omAlloc(len+2);
570          strncpy(s,anf,len+2);
571          s[len+1]='\0';
572          fePrintEcho(s,b);
573          omFree((ADDRESS)s);
574        }
575        else if (/*(startfptr>0) &&*/
576        (currentVoice->buffer[startfptr-1]=='\n'))
577        {
578          char *anf=currentVoice->buffer+startfptr;
579          const char *ss=strchr(anf,'\n');
580          long len;
581          if (ss==NULL) len=strlen(anf);
582          else          len=ss-anf;
583          char *s=(char *)omAlloc(len+2);
584          strncpy(s,anf,len+2);
585          s[len+1]='\0';
586          yylineno++;
587          fePrintEcho(s,b);
588          omFree((ADDRESS)s);
589        }
590      }
591      currentVoice->fptr++;
592      return i;
593    }
594    // no buffer there or e-o-buffer or eoln:
595    if (currentVoice->sw!=BI_buffer)
596    {
597      currentVoice->fptr=0;
598      if (currentVoice->buffer==NULL)
599      {
600        currentVoice->buffer=(char *)omAlloc(MAX_FILE_BUFFER-sizeof(ADDRESS));
601        omMarkAsStaticAddr(currentVoice->buffer);
602      }
603    }
604    offset=0;
605  NewRead:
606    yylineno++;
607    if (currentVoice->sw==BI_stdin)
608    {
609      feShowPrompt();
610      s=fe_fgets_stdin(fe_promptstr,
611                       &(currentVoice->buffer[offset]),
612                       omSizeOfAddr(currentVoice->buffer)-1-offset);
613      //int i=0;
614      //if (s!=NULL)
615      //  while((s[i]!='\0') /*&& (i<MAX_FILE_BUFFER)*/) {s[i] &= (char)127;i++;}
616    }
617    else if (currentVoice->sw==BI_file)
618    {
619      s=fgets(currentVoice->buffer+offset,(MAX_FILE_BUFFER-1-sizeof(ADDRESS))-offset,
620              currentVoice->files);
621    }
622    //else /* BI_buffer */ s==NULL  => return 0
623    // done by the default return
624  }
625  if (s!=NULL)
626  {
627    // handle prot:
628    if (feProt&PROT_I)
629    {
630      fputs(s,feProtFile);
631    }
632    int rc=fePrintEcho(s,b)+1;
633    //s[strlen(s)+1]='\0'; add an second \0 at the end of the string
634    s[rc]='\0';
635    // handel \\ :
636    rc-=3;
637    if ((s[rc]=='\\')&&(currentVoice->sw!=BI_buffer))
638    {
639      s[rc]='\0';
640      offset+=rc;
641      if (offset<(int)omSizeOfAddr(currentVoice->buffer)) goto NewRead;
642    }
643    goto NewBuff;
644  }
645  /* else if (s==NULL) */
646  {
647    const char *err;
648    switch(yy_noeof)
649    {
650      case noeof_brace:
651      case noeof_block:
652        err="{...}";
653        break;
654      case noeof_asstring:
655        err="till `.`";
656        break;
657      case noeof_string:
658        err="string";
659        break;
660      case noeof_bracket:
661        err="(...)";
662        break;
663      case noeof_procname:
664        err="proc";
665        break;
666      case noeof_comment:
667        err="/*...*/";
668        break;
669      default:
670        return 0;
671    }
672    Werror("premature end of file while reading %s",err);
673    return 0;
674  }
675}
676
677/*2
678* init all data structures
679*/
680#ifndef STDIN_FILENO
681#define STDIN_FILENO 0
682#endif
683Voice * feInitStdin(Voice *pp)
684{
685  Voice *p = new Voice;
686  p->files = stdin;
687  #ifdef HAVE_TCL
688  p->sw = (tclmode || isatty(STDIN_FILENO)) ? BI_stdin : BI_file;
689  #else
690  p->sw = (isatty(STDIN_FILENO)) ? BI_stdin : BI_file;
691  #endif
692  if ((pp!=NULL) && (pp->files==stdin))
693  {
694    p->files=freopen("/dev/tty","r",stdin);
695    //stdin=p->files;
696    p->sw = BI_stdin;
697  }
698  p->filename   = omStrDup("STDIN");
699  p->start_lineno   = 1;
700  omMarkAsStaticAddr(p);
701  omMarkAsStaticAddr(p->filename);
702  return p;
703}
704/*****************************************************************
705 *
706 * File handling
707 *
708 *****************************************************************/
709
710FILE * feFopen(const char *path, const char *mode, char *where,
711               int useWerror, int path_only)
712{
713  char longpath[MAXPATHLEN];
714  if (path[0]=='~')
715  {
716    if (path[1] == DIR_SEP)
717    {
718      const char* home = getenv("HOME");
719#ifdef ix86_Win
720      if ((home==NULL)||(!access(home,X_OK)))
721        home = getenv("SINGHOME");
722#endif
723      if (home != NULL)
724      {
725        strcpy(longpath, home);
726        strcat(longpath, &(path[1]));
727        path = longpath;
728      }
729    }
730#if defined(HAVE_PWD_H) && defined(HAVE_GETPWNAM)
731    else
732    {
733      char* dir_sep;
734      struct passwd *pw_entry;
735      strcpy (longpath, path);
736      dir_sep = strchr(longpath, DIR_SEP);
737      *dir_sep = '\0';
738      pw_entry = getpwnam(&longpath[1]);
739      if (pw_entry != NULL)
740      {
741        strcpy(longpath, pw_entry->pw_dir);
742        dir_sep = strchr((char *)path, DIR_SEP);
743        strcat(longpath, dir_sep);
744        path = longpath;
745      }
746    }
747#endif
748  }
749  FILE * f=NULL;
750  if (! path_only)
751  {
752    struct stat statbuf;
753    if ((stat(path,&statbuf)==0)
754    && (S_ISREG(statbuf.st_mode)))
755      f = myfopen(path,mode);
756  }
757  if (where!=NULL) strcpy(where,path);
758  if ((*mode=='r') &&
759      (path[0]!=DIR_SEP) &&
760      ! (path[0] == '.' && path[1] == DIR_SEP) &&
761      (f==NULL))
762  {
763    char found = 0;
764    char* spath = feResource('s');
765    char *s;
766
767    if (where==NULL) s=(char *)omAlloc(250);
768    else             s=where;
769
770    if (spath!=NULL)
771    {
772      char *p,*q;
773      p = spath;
774      while( (q=strchr(p, fePathSep)) != NULL)
775      {
776        *q = '\0';
777        strcpy(s,p);
778        *q = fePathSep;
779        strcat(s, DIR_SEPP);
780        strcat(s, path);
781        if(!access(s, R_OK)) { found++; break; }
782        p = q+1;
783      }
784      if(!found)
785      {
786        strcpy(s,p);
787        strcat(s, DIR_SEPP);
788        strcat(s, path);
789      }
790      f=myfopen(s,mode);
791      if (f!=NULL)
792      {
793        if (where==NULL) omFree((ADDRESS)s);
794        return f;
795      }
796    }
797    else
798    {
799      if (where!=NULL) strcpy(s/*where*/,path);
800      f=myfopen(path,mode);
801    }
802    if (where==NULL) omFree((ADDRESS)s);
803  }
804  if ((f==NULL)&&(useWerror))
805    Werror("cannot open `%s`",path);
806  return f;
807}
808
809static char * feBufferStart;
810  /* only used in StringSet(S)/StringAppend(S)*/
811char * StringAppend(const char *fmt, ...)
812{
813  va_list ap;
814  char *s = feBufferStart; /*feBuffer + strlen(feBuffer);*/
815  int vs;
816  long more;
817  va_start(ap, fmt);
818  if ((more=feBufferStart-feBuffer+strlen(fmt)+100)>feBufferLength)
819  {
820    more = ((more + (8*1024-1))/(8*1024))*(8*1024);
821    int l=s-feBuffer;
822    feBuffer=(char *)omReallocSize((ADDRESS)feBuffer,feBufferLength,
823                                                     more);
824    omMarkAsStaticAddr(feBuffer);
825    feBufferLength=more;
826    s=feBuffer+l;
827#ifndef BSD_SPRINTF
828    feBufferStart=s;
829#endif
830  }
831#ifdef BSD_SPRINTF
832  vsprintf(s, fmt, ap);
833  while (*s!='\0') s++;
834  feBufferStart =s;
835#else
836#ifdef HAVE_VSNPRINTF
837  vs = vsnprintf(s, feBufferLength - (feBufferStart - feBuffer), fmt, ap);
838  if (vs == -1)
839  {
840    assume(0);
841    feBufferStart = feBuffer + feBufferLength -1;
842  }
843  else
844  {
845    feBufferStart += vs;
846  }
847#else
848  feBufferStart += vsprintf(s, fmt, ap);
849#endif
850#endif
851  omCheckAddrSize(feBuffer, feBufferLength);
852  va_end(ap);
853  return feBuffer;
854}
855
856char * StringAppendS(const char *st)
857{
858  if (*st!='\0')
859  {
860    /* feBufferStart is feBuffer + strlen(feBuffer);*/
861    int l;
862    long more;
863    int ll=feBufferStart-feBuffer;
864    if ((more=ll+2+(l=strlen(st)))>feBufferLength)
865    {
866      more = ((more + (8*1024-1))/(8*1024))*(8*1024);
867      feBuffer=(char *)omReallocSize((ADDRESS)feBuffer,feBufferLength,
868                                                       more);
869      feBufferLength=more;
870      feBufferStart=feBuffer+ll;
871    }
872    strcat(feBufferStart, st);
873    feBufferStart +=l;
874  }
875  return feBuffer;
876}
877
878char * StringSetS(const char *st)
879{
880  int l;
881  long more;
882  if ((l=strlen(st))>feBufferLength)
883  {
884    more = ((l + (4*1024-1))/(4*1024))*(4*1024);
885    feBuffer=(char *)omReallocSize((ADDRESS)feBuffer,feBufferLength,
886                                                     more);
887    feBufferLength=more;
888  }
889  strcpy(feBuffer,st);
890  feBufferStart=feBuffer+l;
891  return feBuffer;
892}
893
894#ifdef HAVE_TCL
895extern "C" {
896void PrintTCLS(const char c, const char *s)
897{
898  int l=strlen(s);
899  if (l>0) PrintTCL(c,l,s);
900}
901}
902#endif
903
904extern "C" {
905void WerrorS(const char *s)
906{
907#ifdef HAVE_MPSR
908  if (fe_fgets_stdin==fe_fgets_dummy)
909  {
910    if (feErrors==NULL)
911    {
912      feErrors=(char *)omAlloc(256);
913      feErrorsLen=256;
914      *feErrors = '\0';
915    }
916    else
917    {
918      if (((int)(strlen((char *)s)+ 20 +strlen(feErrors)))>=feErrorsLen)
919      {
920        feErrors=(char *)omReallocSize(feErrors,feErrorsLen,feErrorsLen+256);
921        feErrorsLen+=256;
922      }
923    }
924    strcat(feErrors, "Singular error: ");
925    strcat(feErrors, (char *)s);
926  }
927  else
928#endif
929  {
930#ifdef HAVE_TCL
931    if (tclmode)
932    {
933      PrintTCLS('E',(char *)s);
934      PrintTCLS('E',"\n");
935    }
936    else
937#endif
938    {
939      fwrite("   ? ",1,5,stderr);
940      fwrite((char *)s,1,strlen((char *)s),stderr);
941      fwrite("\n",1,1,stderr);
942      fflush(stderr);
943      if (feProt&PROT_O)
944      {
945        fwrite("   ? ",1,5,feProtFile);
946        fwrite((char *)s,1,strlen((char *)s),feProtFile);
947        fwrite("\n",1,1,feProtFile);
948      }
949    }
950  }
951  errorreported = TRUE;
952#ifdef HAVE_FACTORY
953  // libfac:
954  extern int libfac_interruptflag;
955  libfac_interruptflag=1;
956#endif
957}
958
959void Werror(const char *fmt, ...)
960{
961  va_list ap;
962  va_start(ap, fmt);
963  char *s=(char *)omAlloc(256);
964  vsprintf(s, fmt, ap);
965  WerrorS(s);
966  omFreeSize(s,256);
967  va_end(ap);
968}
969
970void WarnS(const char *s)
971{
972  #define warn_str "// ** "
973#ifdef HAVE_TCL
974  if (tclmode)
975  {
976    PrintTCLS('W',warn_str);
977    PrintTCLS('W',s);
978    PrintTCLS('W',"\n");
979  }
980  else
981#endif
982  if (feWarn) /* ignore warnings if option --no-warn was given */
983  {
984    fwrite(warn_str,1,6,stdout);
985    fwrite(s,1,strlen(s),stdout);
986    fwrite("\n",1,1,stdout);
987    fflush(stdout);
988    if (feProt&PROT_O)
989    {
990      fwrite(warn_str,1,6,feProtFile);
991      fwrite(s,1,strlen(s),feProtFile);
992      fwrite("\n",1,1,feProtFile);
993    }
994  }
995}
996} /* end extern "C" */
997
998void Warn(const char *fmt, ...)
999{
1000  va_list ap;
1001  va_start(ap, fmt);
1002  char *s=(char *)omAlloc(256);
1003  vsprintf(s, fmt, ap);
1004  WarnS(s);
1005  omFreeSize(s,256);
1006  va_end(ap);
1007}
1008
1009
1010// some routines which redirect the output of print to a string
1011static char* sprint = NULL;
1012void SPrintStart()
1013{
1014  sprint = omStrDup("");
1015}
1016
1017static void SPrintS(const char* s)
1018{
1019  omCheckAddr(sprint);
1020  if ((s == NULL)||(*s == '\0')) return;
1021  int ls = strlen(s);
1022
1023  char* ns;
1024  int l = strlen(sprint);
1025  ns = (char*) omAlloc((l + ls + 1)*sizeof(char));
1026  if (l > 0) strcpy(ns, sprint);
1027
1028  strcpy(&(ns[l]), s);
1029  omFree(sprint);
1030  sprint = ns;
1031  omCheckAddr(sprint);
1032}
1033
1034char* SPrintEnd()
1035{
1036  char* ns = sprint;
1037  sprint = NULL;
1038  omCheckAddr(ns);
1039  return ns;
1040}
1041
1042// Print routines
1043extern "C" {
1044void PrintS(const char *s)
1045{
1046  if (sprint != NULL)
1047  {
1048    SPrintS(s);
1049    return;
1050  }
1051  else if (feOut) /* do not print when option --no-out was given */
1052  {
1053
1054#ifdef HAVE_TCL
1055    if (tclmode)
1056    {
1057      PrintTCLS('N',s);
1058    }
1059    else
1060#endif
1061    {
1062      fwrite(s,1,strlen(s),stdout);
1063      fflush(stdout);
1064      if (feProt&PROT_O)
1065      {
1066        fwrite(s,1,strlen(s),feProtFile);
1067      }
1068    }
1069  }
1070}
1071
1072void PrintLn()
1073{
1074  PrintS("\n");
1075}
1076
1077void Print(const char *fmt, ...)
1078{
1079  if (sprint != NULL)
1080  {
1081    va_list ap;
1082    va_start(ap, fmt);
1083    omCheckAddr(sprint);
1084    int ls = strlen(fmt);
1085    if (fmt != NULL && ls > 0)
1086    {
1087      char* ns;
1088      int l = strlen(sprint);
1089      ns = (char*) omAlloc(sizeof(char)*(ls + l + 512));
1090      if (l > 0)  strcpy(ns, sprint);
1091
1092#ifdef HAVE_VSNPRINTF
1093      l = vsnprintf(&(ns[l]), ls+511, fmt, ap);
1094      assume(l != -1);
1095#else
1096      vsprintf(&(ns[l]), fmt, ap);
1097#endif
1098      omCheckAddr(ns);
1099      omFree(sprint);
1100      sprint = ns;
1101    }
1102    va_end(ap);
1103    return;
1104  }
1105  else if (feOut)
1106  {
1107    va_list ap;
1108    va_start(ap, fmt);
1109    int l;
1110    long ls=strlen(fmt);
1111    char *s=(char *)omAlloc(ls+512);
1112#ifdef HAVE_VSNPRINTF
1113    l = vsnprintf(s, ls+511, fmt, ap);
1114    if ((l==-1)||(s[l]!='\0')||(l!=strlen(s)))
1115    {
1116      printf("Print problem: l=%d, fmt=>>%s<<\n",l,fmt);
1117    }
1118#else
1119    vsprintf(s, fmt, ap);
1120#endif
1121    PrintS(s);
1122    omFree(s);
1123    va_end(ap);
1124  }
1125}
1126void PrintNSpaces(const int n)
1127{
1128  int l=n-1;
1129  while(l>=0) { PrintS(" "); l--; }
1130}
1131
1132/* end extern "C" */
1133}
1134
1135#if 0
1136void monitor(char* s, int mode)
1137{
1138  if (feProt)
1139  {
1140    fclose(feProtFile);
1141    feProt = 0;
1142  }
1143  if ((s!=NULL) && (*s!='\0'))
1144  {
1145    feProtFile = myfopen(s,"w");
1146    if (feProtFile==NULL)
1147    {
1148      Werror("cannot open %s",s);
1149      feProt=0;
1150    }
1151    else
1152      feProt = mode;
1153  }
1154}
1155#else
1156void monitor(void *F, int mode)
1157{
1158  if (feProt)
1159  {
1160    fclose(feProtFile);
1161    feProt = 0;
1162  }
1163  if (F!=NULL)
1164  {
1165    feProtFile = (FILE *)F;
1166    feProt = mode;
1167  }
1168}
1169#endif
1170
1171
1172const char* eati(const char *s, int *i)
1173{
1174  int l=0;
1175
1176  if    (*s >= '0' && *s <= '9')
1177  {
1178    *i = 0;
1179    while (*s >= '0' && *s <= '9')
1180    {
1181      *i *= 10;
1182      *i += *s++ - '0';
1183      l++;
1184      if ((l>=MAX_INT_LEN)||((*i) <0))
1185      {
1186        s-=l;
1187        Werror("`%s` greater than %d(max. integer representation)",
1188                s,MAX_INT_VAL);
1189        return s;
1190      }
1191    }
1192  }
1193  else *i = 1;
1194  return s;
1195}
1196#else /* ! STANDALONE_PARSER */
1197#include <stdio.h>
1198
1199#endif
1200
1201#ifdef ix86_Win
1202// Make sure that mode contains binary option
1203FILE* myfopen(const char *path, const char *mode)
1204{
1205  char mmode[4];
1206  int i;
1207  int done = 0;
1208
1209  for (i=0;;i++)
1210  {
1211    mmode[i] = mode[i];
1212    if (mode[i] == '\0') break;
1213    if (mode[i] == 'w') done = 1;
1214    if (mode[i] == 'a') done = 1;
1215    if (mode[i] == 'b') done = 1;
1216  }
1217
1218  if (! done)
1219  {
1220    mmode[i] = 'b';
1221    mmode[i+1] = '\0';
1222  }
1223  return fopen(path, mmode);
1224}
1225#endif
1226// replace "\r\n" by " \n" and "\r" by "\n"
1227
1228size_t myfread(void *ptr, size_t size, size_t nmemb, FILE *stream)
1229{
1230  size_t got = fread(ptr, size, nmemb, stream) * size;
1231  size_t i;
1232
1233  for (i=0; i<got; i++)
1234  {
1235    if ( ((char*) ptr)[i] == '\r')
1236    {
1237      if (i+1 < got && ((char*) ptr)[i+1] == '\n')
1238        ((char*) ptr)[i] = ' ';
1239      else
1240        ((char*) ptr)[i] = '\n';
1241    }
1242  }
1243  return got;
1244}
Note: See TracBrowser for help on using the repository browser.