source: git/kernel/febase.cc @ 690e21e

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