1 
2 /****************************************
3 *  Computer Algebra System SINGULAR     *
4 ****************************************/
5 /*
6 * ABSTRACT: output system
7 */
8 
9 #include "misc/auxiliary.h"
10 
11 #include "reporter/reporter.h"
12 #include "resources/feResource.h"
13 #include "resources/feFopen.h"
14 //#include "options.h"
15 #include "omalloc/omalloc.h"
16 
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include "misc/mylimits.h"
20 #include <stdarg.h>
21 #include <sys/stat.h>
22 #include <ctype.h>
23 #include <unistd.h>
24 
25 #ifdef HAVE_PWD_H
26 #include <pwd.h>
27 #endif
28 
29 
30 #define fePutChar(c) fputc((unsigned char)(c),stdout)
31 /*0 implementation */
32 
33 // output/print buffer:
34 #define INITIAL_PRINT_BUFFER 24*1024L
35 // line buffer for reading:
36 // minimal value for MAX_FILE_BUFFER: 4*4096 - see Tst/Long/gcd0_l.tst
37 // this is an upper limit for the size of monomials/numbers read via the interpreter
38 #define MAX_FILE_BUFFER 4*4096
39 STATIC_VAR long feBufferLength=0;
40 STATIC_VAR char * feBuffer=NULL;
41 STATIC_VAR long feBufferLength_save[8];
42 STATIC_VAR char * feBuffer_save[8];
43 STATIC_VAR int feBuffer_cnt=0;
44 STATIC_VAR char * feBufferStart_save[8];
45 
46 
47 VAR char *  feErrors=NULL;
48 VAR int     feErrorsLen=0;
49 VAR BOOLEAN feWarn = TRUE;
50 VAR BOOLEAN feOut = TRUE;
51 
52 //void (*WerrorS_callback)(const char *s) = NULL;
53 
54 const char feNotImplemented[]="not implemented";
55 
56 VAR int feProt = FALSE;
57 VAR FILE*   feProtFile;
58 
59 STATIC_VAR char * feBufferStart;
60   /* only used in StringSet(S)/StringAppend(S)*/
StringAppend(const char * fmt,...)61 void StringAppend(const char *fmt, ...)
62 {
63   va_list ap;
64   char *s = feBufferStart; /*feBuffer + strlen(feBuffer);*/
65   int vs;
66   long more;
67   va_start(ap, fmt);
68   if ((more=feBufferStart-feBuffer+strlen(fmt)+100)>feBufferLength)
69   {
70     more = ((more + (8*1024-1))/(8*1024))*(8*1024);
71     int l=s-feBuffer;
72     feBuffer=(char *)omReallocSize((void *)feBuffer,feBufferLength,
73                                                      more);
74 #if (!defined(SING_NDEBUG)) && (!defined(OM_NDEBUG))
75     omMarkAsStaticAddr(feBuffer);
76 #endif
77     feBufferLength=more;
78     s=feBuffer+l;
79 #ifndef BSD_SPRINTF
80     feBufferStart=s;
81 #endif
82   }
83 #ifdef BSD_SPRINTF
84   vsprintf(s, fmt, ap);
85   while (*s!='\0') s++;
86   feBufferStart =s;
87 #else
88 #ifdef HAVE_VSNPRINTF
89   vs = vsnprintf(s, feBufferLength - (feBufferStart - feBuffer), fmt, ap);
90   if (vs == -1)
91   {
92     assume(0);
93     feBufferStart = feBuffer + feBufferLength -1;
94   }
95   else
96   {
97     feBufferStart += vs;
98   }
99 #else
100   feBufferStart += vsprintf(s, fmt, ap);
101 #endif
102 #endif
103   omCheckAddrSize(feBuffer, feBufferLength);
104   va_end(ap);
105 }
106 
StringAppendS(const char * st)107 void StringAppendS(const char *st)
108 {
109   if (*st!='\0')
110   {
111     /* feBufferStart is feBuffer + strlen(feBuffer);*/
112     int l=strlen(st);
113     long more;
114     int ll=feBufferStart-feBuffer;
115     if ((more=ll+2+l)>feBufferLength)
116     {
117       more = ((more + (8*1024-1))/(8*1024))*(8*1024);
118       feBuffer=(char *)omreallocSize((void *)feBuffer,feBufferLength,
119                                                        more);
120       feBufferLength=more;
121       feBufferStart=feBuffer+ll;
122     }
123     strncat(feBufferStart, st,l);
124     feBufferStart +=l;
125   }
126 }
127 
StringSetS(const char * st)128 void StringSetS(const char *st)
129 {
130   feBuffer_save[feBuffer_cnt]=feBuffer;
131   feBuffer=(char*)omAlloc0(INITIAL_PRINT_BUFFER);
132   feBufferLength_save[feBuffer_cnt]=feBufferLength;
133   feBufferLength=INITIAL_PRINT_BUFFER;
134   feBufferStart_save[feBuffer_cnt]=feBufferStart;
135   feBufferStart=feBuffer;
136   feBuffer_cnt++;
137   assume(feBuffer_cnt<8);
138   int l=strlen(st);
139   long more;
140   if (l>feBufferLength)
141   {
142     more = ((l + (4*1024-1))/(4*1024))*(4*1024);
143     feBuffer=(char *)omReallocSize((ADDRESS)feBuffer,feBufferLength,
144                                                      more);
145     feBufferLength=more;
146   }
147   strcpy(feBuffer,st);
148   feBufferStart=feBuffer+l;
149 }
150 
StringEndS()151 char * StringEndS()
152 {
153   char *r=feBuffer;
154   feBuffer_cnt--;
155   assume(feBuffer_cnt >=0);
156   feBuffer=feBuffer_save[feBuffer_cnt];
157   feBufferLength=feBufferLength_save[feBuffer_cnt];
158   feBufferStart=feBufferStart_save[feBuffer_cnt];
159   if (strlen(r)<1024)
160   {
161     // if the used buffer is a "small block",
162     // substitue the "large" initial block by a small one
163     char *s=omStrDup(r); omFree(r); r=s;
164   }
165   return r;
166 }
167 
WerrorS_batch(const char * s)168 void WerrorS_batch(const char *s)
169 {
170   if (feErrors==NULL)
171   {
172     feErrors=(char *)omAlloc(256);
173     feErrorsLen=256;
174     *feErrors = '\0';
175   }
176   else
177   {
178     if (((int)(strlen((char *)s)+ 20 +strlen(feErrors)))>=feErrorsLen)
179     {
180       feErrors=(char *)omReallocSize(feErrors,feErrorsLen,feErrorsLen+256);
181       feErrorsLen+=256;
182     }
183   }
184   strcat(feErrors, "Singular error: ");
185   strcat(feErrors, (char *)s);
186   errorreported = TRUE;
187 }
188 
Werror(const char * fmt,...)189 void Werror(const char *fmt, ...)
190 {
191   va_list ap;
192   va_start(ap, fmt);
193   char *s=(char *)omAlloc(256);
194   vsprintf(s, fmt, ap);
195   WerrorS(s);
196   omFreeSize(s,256);
197   va_end(ap);
198 }
199 
200 VAR void (*WarnS_callback)(const char *s) = NULL;
201 
WarnS(const char * s)202 void WarnS(const char *s)
203 {
204   #define warn_str "// ** "
205   if (feWarn) /* ignore warnings if option --no-warn was given */
206   {
207     if (WarnS_callback==NULL)
208     {
209       fwrite(warn_str,1,6,stdout);
210       fwrite(s,1,strlen(s),stdout);
211       fwrite("\n",1,1,stdout);
212       fflush(stdout);
213       if (feProt&SI_PROT_O)
214       {
215         fwrite(warn_str,1,6,feProtFile);
216         fwrite(s,1,strlen(s),feProtFile);
217         fwrite("\n",1,1,feProtFile);
218       }
219     }
220     else
221     {
222       WarnS_callback(s);
223     }
224   }
225 }
226 
Warn(const char * fmt,...)227 void Warn(const char *fmt, ...)
228 {
229   va_list ap;
230   va_start(ap, fmt);
231   char *s=(char *)omAlloc(256);
232 #ifdef HAVE_VSNPRINTF
233   vsnprintf(s, 256, fmt, ap);
234 #else
235   vsprintf(s, fmt, ap);
236 #endif
237   WarnS(s);
238   omFreeSize(s,256);
239   va_end(ap);
240 }
241 
242 
243 // some routines which redirect the output of print to a string
244 STATIC_VAR char* sprint = NULL;
245 STATIC_VAR char* sprint_backup = NULL;
SPrintStart()246 void SPrintStart()
247 {
248   if (sprint!=NULL)
249   {
250     if (sprint_backup!=NULL) WerrorS("internal error: SPrintStart");
251     else sprint_backup=sprint;
252   }
253   sprint = omStrDup("");
254 }
255 
SPrintS(const char * s)256 static inline void SPrintS(const char* s)
257 {
258   omCheckAddr(sprint);
259   if ((s == NULL)||(*s == '\0')) return;
260   int ls = strlen(s);
261 
262   char* ns;
263   int l = strlen(sprint);
264   ns = (char*) omAlloc((l + ls + 1)*sizeof(char));
265   if (l > 0) strcpy(ns, sprint);
266 
267   strcpy(&(ns[l]), s);
268   omFree(sprint);
269   sprint = ns;
270   omCheckAddr(sprint);
271 }
272 
SPrintEnd()273 char* SPrintEnd()
274 {
275   char* ns = sprint;
276   sprint = sprint_backup;
277   sprint_backup=NULL;
278   omCheckAddr(ns);
279   return ns;
280 }
281 
282 // Print routines
283 extern "C" {
PrintS(const char * s)284 void PrintS(const char *s)
285 {
286   if (sprint != NULL)
287   {
288     SPrintS(s);
289     return;
290   }
291   else if (feOut) /* do not print when option --no-out was given */
292   {
293 
294     if (PrintS_callback!=NULL)
295     {
296       PrintS_callback(s);
297     }
298     else
299     {
300       fwrite(s,1,strlen(s),stdout);
301       fflush(stdout);
302       if (feProt&SI_PROT_O)
303       {
304         fwrite(s,1,strlen(s),feProtFile);
305       }
306     }
307   }
308 }
309 
PrintLn()310 void PrintLn()
311 {
312   PrintS("\n");
313 }
314 
Print(const char * fmt,...)315 void Print(const char *fmt, ...)
316 {
317   if (sprint != NULL)
318   {
319     va_list ap;
320     va_start(ap, fmt);
321     omCheckAddr(sprint);
322     int ls = strlen(fmt);
323     if (fmt != NULL && ls > 0)
324     {
325       char* ns;
326       int l = strlen(sprint);
327       ns = (char*) omAlloc(sizeof(char)*(ls + l + 512));
328       if (l > 0)  strcpy(ns, sprint);
329 
330 #ifdef HAVE_VSNPRINTF
331       l = vsnprintf(&(ns[l]), ls+511, fmt, ap);
332       assume(l != -1);
333 #else
334       vsprintf(&(ns[l]), fmt, ap);
335 #endif
336       omCheckAddr(ns);
337       omFree(sprint);
338       sprint = ns;
339     }
340     va_end(ap);
341     return;
342   }
343   else if (feOut)
344   {
345     va_list ap;
346     va_start(ap, fmt);
347     int l;
348     long ls=strlen(fmt);
349     char *s=(char *)omAlloc(ls+512);
350 #ifdef HAVE_VSNPRINTF
351     l = vsnprintf(s, ls+511, fmt, ap);
352     if ((l==-1)||(s[l]!='\0')||(l!=(int)strlen(s)))
353     {
354       printf("Print problem: l=%d, fmt=>>%s<<\n",l,fmt);
355     }
356 #else
357     vsprintf(s, fmt, ap);
358 #endif
359     PrintS(s);
360     omFree(s);
361     va_end(ap);
362   }
363 }
PrintNSpaces(const int n)364 void PrintNSpaces(const int n)
365 {
366   int l=n-1;
367   while(l>=0) { PrintS(" "); l--; }
368 }
369 
370 /* end extern "C" */
371 }
372 
eati(const char * s,int * i)373 const char* eati(const char *s, int *i)
374 {
375   int l=0;
376 
377   if    (*s >= '0' && *s <= '9')
378   {
379     *i = 0;
380     while (*s >= '0' && *s <= '9')
381     {
382       *i *= 10;
383       *i += *s++ - '0';
384       l++;
385       if ((l>=MAX_INT_LEN)||((*i) <0))
386       {
387         s-=l;
388         Werror("`%s` greater than %d(max. integer representation)",
389                 s,MAX_INT_VAL);
390         return s;
391       }
392     }
393   }
394   else *i = 1;
395   return s;
396 }
397 
feStringAppendResources(int warn)398 void feStringAppendResources(int warn)
399 {
400   int i = 0;
401   char* r;
402   StringAppend("%-10s:\t%s\n", "argv[0]", feArgv0);
403   while (feResourceConfigs[i].key != NULL)
404   {
405     r = feResource(feResourceConfigs[i].key, warn);
406     StringAppend("%-10s:\t%s\n", feResourceConfigs[i].key,
407                  (r != NULL ? r : ""));
408     i++;
409   }
410 }
411