1 /*
2  *  gretl -- Gnu Regression, Econometrics and Time-series Library
3  *  Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #include "libgretl.h"
21 #include "libset.h"
22 #include "gretl_func.h"
23 #include "uservar.h"
24 #include <stdarg.h>
25 #include <errno.h>
26 #include <glib/gprintf.h>
27 
28 /**
29  * SECTION:gretl_prn
30  * @short_description: gretl printing struct
31  * @title: PRN
32  * @include: libgretl.h
33  *
34  * Most libgretl functions that print output call for a
35  * pointer-to-PRN as one of their arguments. The PRN type is
36  * an opaque structure, constructed and manipulated by the
37  * functions listed here. It is used as a means of generalizing
38  * the printing operation, which may be to a regular file, a
39  * temporary file or a buffer.
40  *
41  * To get hold of a PRN use gretl_print_new() or one of the more
42  * specific constructors, and to free it use gretl_print_destroy().
43  * If you want to use a PRN dirctly for printing in your own code, use
44  * the functions pprintf(), pputs() and pputc(). These are
45  * counterparts to the standard C functions fprintf, fputs and
46  * fputc, but note that with pputs and pputc the PRN argument
47  * must be given first (unlike fputs and fputc in which the
48  * FILE argument goes last).
49  *
50  * Note that whenever a PRN appears as a function parameter
51  * in libgretl it is OK to give a NULL argument: in that case
52  * pprintf(), pputs() and pputc() are no-ops.
53  */
54 
55 struct PRN_ {
56     FILE *fp;          /* file to which to print, or NULL */
57     gzFile fz;         /* gzipped file target, or NULL */
58     char *buf;         /* buffer to which to print, or NULL */
59     size_t bufsize;    /* allocated size of buffer */
60     size_t blen;       /* string length of buffer */
61     int savepos;       /* saved position in stream or buffer */
62     GArray *fplist;    /* stack for use with output redirection */
63     PrnFormat format;  /* plain, TeX, RTF */
64     gint8 fixed;       /* non-zero for fixed-size buffer */
65     gint8 gbuf;        /* non-zero for buffer obtained via GLib */
66     guint8 nlcount;    /* count of trailing newlines */
67     char delim;        /* CSV field delimiter */
68     char *fname;       /* temp file name, or NULL */
69 };
70 
71 struct fpinfo_ {
72     FILE *fp;      /* stream to which we're printing */
73     int level;     /* level of depth of redicrection */
74     gchar *fname;  /* name of file or NULL */
75     gchar *strvar; /* associated string variable or NULL */
76 };
77 
78 typedef struct fpinfo_ fpinfo;
79 
80 #define PRN_DEBUG 0
81 
prn_destroy_fp_list(PRN * prn)82 static void prn_destroy_fp_list (PRN *prn)
83 {
84     int i, n = prn->fplist->len;
85     fpinfo *fi;
86 
87     for (i=n-1; i>=0; i--) {
88 	fi = &g_array_index(prn->fplist, fpinfo, i);
89 	if (fi != NULL) {
90 	    if (fi->fp != NULL && fi->fp != prn->fp &&
91 		fi->fp != stdout && fi->fp != stderr) {
92 		fclose(fi->fp);
93 	    }
94 	    if (fi->fname != NULL) {
95 		g_free(fi->fname);
96 	    }
97 	    if (fi->strvar != NULL) {
98 		g_free(fi->strvar);
99 	    }
100 	    g_array_remove_index(prn->fplist, i);
101 	}
102     }
103 
104     g_array_free(prn->fplist, TRUE);
105     prn->fplist = NULL;
106 }
107 
prn_fp_list_active(PRN * prn)108 static int prn_fp_list_active (PRN *prn)
109 {
110     return prn->fplist != NULL && prn->fplist->len > 0;
111 }
112 
113 /**
114  * gretl_print_destroy:
115  * @prn: pointer to gretl printing struct.
116  *
117  * Close a gretl printing struct and free any associated resources.
118  */
119 
gretl_print_destroy(PRN * prn)120 void gretl_print_destroy (PRN *prn)
121 {
122     if (prn == NULL) {
123 	return;
124     }
125 
126     if (prn->fplist != NULL) {
127 	prn_destroy_fp_list(prn);
128     }
129 
130     if (prn->fp != NULL) {
131 	if (prn->fp == stdout) {
132 	    fflush(stdout);
133 	} else if (prn->fp != stderr) {
134 #if PRN_DEBUG
135 	    fprintf(stderr, "gretl_print_destroy: prn=%p, closing fp at %p\n",
136 		    (void *) prn, (void *) prn->fp);
137 #endif
138 	    fclose(prn->fp);
139 	}
140     } else if (prn->fz != NULL) {
141 	gzclose(prn->fz);
142     }
143 
144     if (prn->fname != NULL) {
145 	/* prn had a tempfile attached */
146 	gretl_remove(prn->fname);
147 	free(prn->fname);
148     }
149 
150     if (prn->buf != NULL) {
151 #if PRN_DEBUG
152   	fprintf(stderr, "gretl_print_destroy: freeing buffer at %p\n",
153 		(void *) prn->buf);
154 #endif
155 	if (prn->gbuf) {
156 	    /* the buffer was obtained from GLib */
157 	    g_free(prn->buf);
158 	} else {
159 	    free(prn->buf);
160 	}
161     }
162 
163     free(prn);
164 }
165 
prn_add_tempfile(PRN * prn)166 static int prn_add_tempfile (PRN *prn)
167 {
168     const char *dotdir = gretl_dotdir();
169     int n = strlen(dotdir) + 16;
170     int err = 0;
171 
172     prn->fname = malloc(n);
173     if (prn->fname == NULL) {
174 	return E_ALLOC;
175     }
176 
177     sprintf(prn->fname, "%sprntmp.XXXXXX", dotdir);
178     prn->fp = gretl_mktemp(prn->fname, "w+");
179 
180 #if PRN_DEBUG
181     fprintf(stderr, "prn_add_tempfile: '%s' at %p\n",
182 	    prn->fname, (void *) prn->fp);
183 #endif
184 
185     if (prn->fp == NULL) {
186 	free(prn->fname);
187 	prn->fname = NULL;
188 	err = E_FOPEN;
189     }
190 
191     return err;
192 }
193 
real_gretl_print_new(PrnType ptype,const char * fname,char * buf,FILE * fp,int zcomp,int * perr)194 static PRN *real_gretl_print_new (PrnType ptype,
195 				  const char *fname,
196 				  char *buf,
197 				  FILE *fp,
198 				  int zcomp,
199 				  int *perr)
200 {
201     PRN *prn = malloc(sizeof *prn);
202     int err = 0;
203 
204     if (prn == NULL) {
205 	if (perr != NULL) {
206 	    *perr = E_ALLOC;
207 	}
208 	return NULL;
209     }
210 
211     prn->fp = NULL;
212     prn->fz = NULL;
213     prn->fplist = NULL;
214     prn->buf = NULL;
215     prn->bufsize = 0;
216     prn->blen = 0;
217     prn->savepos = -1;
218     prn->format = GRETL_FORMAT_TXT;
219     prn->fixed = 0;
220     prn->gbuf = 0;
221     prn->nlcount = 0;
222     prn->delim = ',';
223     prn->fname = NULL;
224 
225     if (ptype == GRETL_PRINT_STREAM) {
226 	prn->fp = fp;
227     } else if (ptype == GRETL_PRINT_FILE) {
228 	prn->fp = gretl_fopen(fname, "wb");
229 	if (prn->fp == NULL) {
230 	    err = E_FOPEN;
231 	    free(prn);
232 	    prn = NULL;
233 	}
234     } else if (ptype == GRETL_PRINT_GZFILE) {
235 	prn->fz = gretl_gzopen(fname, "wb");
236 	if (prn->fz == NULL) {
237 	    err = E_FOPEN;
238 	    free(prn);
239 	    prn = NULL;
240 	} else if (zcomp >= 0) {
241 	    gzsetparams(prn->fz, zcomp, Z_DEFAULT_STRATEGY);
242 	}
243     } else if (ptype == GRETL_PRINT_TEMPFILE) {
244 	err = prn_add_tempfile(prn);
245 	if (err) {
246 	    free(prn);
247 	    prn = NULL;
248 	} else {
249 	    prn->savepos = 0;
250 	}
251     } else if (ptype == GRETL_PRINT_STDOUT) {
252 	prn->fp = stdout;
253     } else if (ptype == GRETL_PRINT_STDERR) {
254 	prn->fp = stderr;
255     } else if (ptype == GRETL_PRINT_BUFFER) {
256 	if (buf != NULL) {
257 	    prn->buf = buf;
258 	    prn->fixed = 1;
259 #if PRN_DEBUG
260 	    fprintf(stderr, "prn with fixed buffer\n");
261 #endif
262 	} else {
263 	    int p = pprintf(prn, "@init");
264 
265 	    if (p < 0) {
266 		err = E_ALLOC;
267 		free(prn);
268 		prn = NULL;
269 	    }
270 	}
271     }
272 
273 #if PRN_DEBUG
274     fprintf(stderr, "real_gretl_print_new at %p: type=%d, fname='%s', "
275 	    "buf=%p, fp=%p\n", (void *) prn, ptype, fname,
276 	    (void *) buf, (void *) fp);
277 #endif
278 
279     if (perr != NULL) {
280 	*perr = err;
281     }
282 
283     return prn;
284 }
285 
286 /**
287  * gretl_print_new:
288  * @ptype: code indicating the desired printing mode.
289  * @err: location to receive error code, or NULL.
290  *
291  * Create and initialize a gretl printing struct. If @ptype
292  * is %GRETL_PRINT_BUFFER, output will go to an automatically
293  * resized buffer; if @ptype is %GRETL_PRINT_STDOUT or
294  * %GRETL_PRINT_STDERR output goes to %stdout or %stderr
295  * respectively.
296  *
297  * If you want a named file associated with the struct, use
298  * #gretl_print_new_with_filename instead; if you want to
299  * attach a fixed, pre-allocated text buffer, use
300  * #gretl_print_new_with_buffer.
301  *
302  * Returns: pointer to newly created struct, or NULL on failure.
303  */
304 
gretl_print_new(PrnType ptype,int * err)305 PRN *gretl_print_new (PrnType ptype, int *err)
306 {
307     if (ptype == GRETL_PRINT_FILE) {
308 	fprintf(stderr, "gretl_print_new: needs a filename\n");
309 	return NULL;
310     }
311 
312 #if PRN_DEBUG
313     fprintf(stderr, "gretl_print_new() called, type = %d\n", ptype);
314 #endif
315 
316     return real_gretl_print_new(ptype, NULL, NULL, NULL, -1, err);
317 }
318 
319 /**
320  * gretl_print_new_with_filename:
321  * @fname: name of the file to be opened for writing.
322  * @err: location to receive error code.
323  *
324  * Create and initialize a gretl printing struct, with
325  * output directed to the named file.
326  *
327  * Returns: pointer to newly created struct, or NULL on failure.
328  */
329 
gretl_print_new_with_filename(const char * fname,int * err)330 PRN *gretl_print_new_with_filename (const char *fname, int *err)
331 {
332     if (fname == NULL) {
333 	fprintf(stderr, _("gretl_prn_new: Must supply a filename\n"));
334 	return NULL;
335     }
336 
337     return real_gretl_print_new(GRETL_PRINT_FILE, fname,
338 				NULL, NULL, -1, err);
339 }
340 
341 /**
342  * gretl_gzip_print_new:
343  * @fname: name of the compressed file to be opened for writing.
344  * @comp_level: -1 for default, or integer 0 to 9.
345  * @err: location to receive error code.
346  *
347  * Create and initialize a gretl printing struct, with
348  * output directed to the named compressed file.
349  *
350  * Returns: pointer to newly created struct, or NULL on failure.
351  */
352 
gretl_gzip_print_new(const char * fname,int comp_level,int * err)353 PRN *gretl_gzip_print_new (const char *fname, int comp_level,
354 			   int *err)
355 {
356     if (fname == NULL) {
357 	fprintf(stderr, "gretl_gzip_print_new: must supply a filename\n");
358 	return NULL;
359     } else if (comp_level < -1 || comp_level > 9) {
360 	fprintf(stderr, "gretl_gzip_print_new: invalid compression level\n");
361 	*err = E_INVARG;
362 	return NULL;
363     }
364 
365     return real_gretl_print_new(GRETL_PRINT_GZFILE, fname,
366 				NULL, NULL, comp_level, err);
367 }
368 
369 /**
370  * gretl_print_new_with_tempfile:
371  * @err: location to receive error code.
372  *
373  * Create and initialize a gretl printing struct, with
374  * output directed to a temporary file, which is deleted
375  * when the printing struct is destroyed.
376  *
377  * Returns: pointer to newly created struct, or NULL on failure.
378  */
379 
gretl_print_new_with_tempfile(int * err)380 PRN *gretl_print_new_with_tempfile (int *err)
381 {
382     return real_gretl_print_new(GRETL_PRINT_TEMPFILE, NULL,
383 				NULL, NULL, -1, err);
384 }
385 
386 /**
387  * gretl_print_has_tempfile:
388  * @prn: printing struct to test.
389  *
390  * Returns: 1 if @prn has a tempfile attached, else 0.
391  */
392 
gretl_print_has_tempfile(PRN * prn)393 int gretl_print_has_tempfile (PRN *prn)
394 {
395     if (prn != NULL && prn->fname != NULL && prn->fp != NULL) {
396 	return strstr(prn->fname, "prntmp.") != NULL;
397     } else {
398 	return 0;
399     }
400 }
401 
402 /**
403  * gretl_print_get_tempfile_name:
404  * @prn: printing struct to test.
405  *
406  * Returns: if @prn has a tempfile attached, return the name
407  * of that file, otherwise return NULL.
408  */
409 
gretl_print_get_tempfile_name(PRN * prn)410 const char *gretl_print_get_tempfile_name (PRN *prn)
411 {
412     if (prn != NULL) {
413 	return prn->fname;
414     } else {
415 	return NULL;
416     }
417 }
418 
419 /**
420  * gretl_print_new_with_buffer:
421  * @buf: pre-allocated text buffer.
422  *
423  * Creates and initializes a gretl printing struct, with
424  * fixed text buffer @buf.  Fails if @buf is NULL.  This is a
425  * convenience function: you can't use #pprintf, #pputs or
426  * #pputc with a printing struct obtained in this way.
427  *
428  * Note that @buf will be freed if and when #gretl_print_destroy
429  * is called on the #PRN pointer obtained.
430  *
431  * Returns: pointer to newly created struct, or NULL on failure.
432  */
433 
gretl_print_new_with_buffer(char * buf)434 PRN *gretl_print_new_with_buffer (char *buf)
435 {
436     if (buf == NULL) {
437 	return NULL;
438     } else {
439 	return real_gretl_print_new(GRETL_PRINT_BUFFER, NULL,
440 				    buf, NULL, -1, NULL);
441     }
442 }
443 
444 /**
445  * gretl_print_new_with_gchar_buffer:
446  * @buf: pre-allocated text buffer.
447  *
448  * Just as gretl_print_new_with_buffer() except that the buffer is
449  * of pointer-to-gchar type, as obtained from one or other GLib
450  * function. This means that when the #PRN is detroyed the
451  * buffer will be freed using GLib's g_free function rather than
452  * the standard C library's free function.
453  *
454  * Returns: pointer to newly created struct, or NULL on failure.
455  */
456 
gretl_print_new_with_gchar_buffer(gchar * buf)457 PRN *gretl_print_new_with_gchar_buffer (gchar *buf)
458 {
459     PRN *prn = NULL;
460 
461     if (buf != NULL) {
462 	prn = real_gretl_print_new(GRETL_PRINT_BUFFER, NULL,
463 				   buf, NULL, -1, NULL);
464 	if (prn != NULL) {
465 	    prn->gbuf = 1;
466 	}
467     }
468 
469     return prn;
470 }
471 
472 /**
473  * gretl_print_new_with_stream:
474  * @fp: pre-opened stream.
475  *
476  * Creates and initializes a gretl printing struct, with
477  * printing to @fp.
478  *
479  * Note that @fp will be closed if and when #gretl_print_destroy
480  * is called on the #PRN pointer obtained.
481  *
482  * Returns: pointer to newly created struct, or NULL on failure.
483  */
484 
gretl_print_new_with_stream(FILE * fp)485 PRN *gretl_print_new_with_stream (FILE *fp)
486 {
487     if (fp == NULL) {
488 	return NULL;
489     } else {
490 	return real_gretl_print_new(GRETL_PRINT_STREAM, NULL,
491 				    NULL, fp, -1, NULL);
492     }
493 }
494 
495 /**
496  * gretl_print_detach_stream
497  * @prn: printing struct to operate on.
498  *
499  * Sets the stream member of @prn to NULL so that @prn can
500  * be destroyed without closing the associated stream.  May be
501  * used in conjunction with gretl_print_new_with_stream().
502  */
503 
gretl_print_detach_stream(PRN * prn)504 void gretl_print_detach_stream (PRN *prn)
505 {
506     prn->fp = NULL;
507 }
508 
509 /**
510  * gretl_print_rename_file:
511  * @prn: printing struct to operate on.
512  * @oldpath: name of current file (or NULL if @prn was
513  * set up using #gretl_print_new_with_tempfile).
514  * @newpath: new name for file.
515  *
516  * If @prn is printing to a %FILE pointer, rename the
517  * file to which it is printing and switch the stream
518  * to the new file.
519  *
520  * Returns: 0 on success, 1 on error.
521  */
522 
gretl_print_rename_file(PRN * prn,const char * oldpath,const char * newpath)523 int gretl_print_rename_file (PRN *prn, const char *oldpath,
524 			     const char *newpath)
525 {
526     int err = 0;
527 
528     if (prn == NULL) {
529 	fprintf(stderr, "gretl_print_rename_file: prn is NULL\n");
530 	return E_DATA;
531     }
532 
533     if (prn->fp == NULL || prn_fp_list_active(prn)) {
534 	return E_DATA;
535     }
536 
537 #if PRN_DEBUG
538     fprintf(stderr, "gretl_print_rename_file, prn at %p:\n oldpath='%s'\n"
539 	    " newpath='%s'\n prn->fp=%p (closing)\n", (void *) prn,
540 	    oldpath, newpath, (void *) prn->fp);
541     fprintf(stderr, " (old prn->fname = '%s')\n", prn->fname);
542 #endif
543 
544     fclose(prn->fp);
545     prn->fp = NULL;
546 
547     if (oldpath == NULL && prn->fname != NULL) {
548 	/* renaming from tempfile */
549 	err = gretl_rename(prn->fname, newpath);
550     } else {
551 	err = gretl_rename(oldpath, newpath);
552     }
553 
554     if (err) {
555 	fprintf(stderr, "%s\n", gretl_errmsg_get());
556     } else {
557 	/* re-open the stream under its new name */
558 	prn->fp = gretl_fopen(newpath, "a");
559 #if PRN_DEBUG
560 	fprintf(stderr, "gretl_print_rename_file: new fp=%p\n", prn->fp);
561 #endif
562 	if (prn->fname != NULL) {
563 	    /* @prn originally used a tempfile: the record of
564 	       the temporary filename should be deleted
565 	    */
566 	    free(prn->fname);
567 	    prn->fname = NULL;
568 	}
569     }
570 
571     return err;
572 }
573 
574 /**
575  * gretl_print_reset_buffer:
576  * @prn: printing struct to operate on.
577  *
578  * If @prn has an attached buffer, write a NUL byte to
579  * the start of the buffer and reset the count of bytes
580  * printed to zero.  The next call to @pprintf or
581  * similar will then overwite rather than cumulating
582  * the printed content.
583  *
584  * Returns: 0 on success, 1 if @prn has no buffer.
585  */
586 
gretl_print_reset_buffer(PRN * prn)587 int gretl_print_reset_buffer (PRN *prn)
588 {
589     int err = 0;
590 
591     if (prn != NULL && prn->buf != NULL) {
592 	*prn->buf = '\0';
593 	prn->blen = 0;
594     } else {
595 	err = 1;
596     }
597 
598     return err;
599 }
600 
601 /**
602  * gretl_print_get_buffer:
603  * @prn: printing struct.
604  *
605  * Obtain a pointer to the buffer associated
606  * with @prn, if any.  This pointer must not be
607  * modified in any way.
608  *
609  * Returns: the buffer, or NULL on failure.
610  */
611 
gretl_print_get_buffer(PRN * prn)612 const char *gretl_print_get_buffer (PRN *prn)
613 {
614     return (prn != NULL)? prn->buf : NULL;
615 }
616 
617 /**
618  * gretl_print_get_trimmed_buffer:
619  * @prn: printing struct.
620  *
621  * Obtain a pointer to the buffer associated
622  * with @prn, if any.  This pointer must not be
623  * modified in any way.  An opening newline
624  * is skipped and any trailing white space is
625  * substituted by NULs.
626  *
627  * Returns: the buffer, or NULL on failure.
628  */
629 
gretl_print_get_trimmed_buffer(PRN * prn)630 const char *gretl_print_get_trimmed_buffer (PRN *prn)
631 {
632     char *buf = (prn != NULL)? prn->buf : NULL;
633 
634     if (buf != NULL) {
635 	int i, n;
636 
637 	if (*buf == '\n') {
638 	    buf++;
639 	}
640 	n = strlen(buf);
641 	for (i=n-1; i>0; i--) {
642 	    if (buf[i] == '\n' && buf[i-1] == '\n') {
643 		buf[i] = '\0';
644 	    } else {
645 		break;
646 	    }
647 	}
648     }
649 
650     return buf;
651 }
652 
653 /**
654  * gretl_print_get_size:
655  * @prn: printing struct.
656  * @width: location to receive width, or NULL.
657  * @height: location to receive height, or NULL.
658  *
659  * If @prn has a non-null buffer attached, provides
660  * the width and/or height of the buffer, the width in
661  * characters and the height in lines. This function is
662  * intended for use with text designed for printing in
663  * a GUI window, and with "reasonable" line lengths for
664  * that context; if the lines are too long (more than
665  * 120 UTF-8 characters) the values written to @width
666  * and/or @height will be zero.
667  */
668 
gretl_print_get_size(PRN * prn,int * width,int * height)669 void gretl_print_get_size (PRN *prn, int *width, int *height)
670 {
671     int w = 0, h = 0;
672 
673     if (prn != NULL && prn->buf != NULL) {
674 	char line[128];
675 	int lw;
676 
677 	bufgets_init(prn->buf);
678 	while (bufgets(line, sizeof line, prn->buf)) {
679 	    lw = g_utf8_strlen(line, -1) - 1;
680 	    if (lw > 120) {
681 		w = h = 0;
682 		break;
683 	    }
684 	    if (lw > w) {
685 		w = lw;
686 	    }
687 	    h++;
688 	}
689 	bufgets_finalize(prn->buf);
690     }
691 
692     if (width != NULL) {
693 	*width = w;
694     }
695 
696     if (height != NULL) {
697 	*height = h;
698     }
699 }
700 
701 /**
702  * gretl_print_steal_buffer:
703  * @prn: printing struct.
704  *
705  * Obtain a pointer to the buffer associated with @prn,
706  * if any.  The pointer on @prn itself is set to NULL
707  * and the caller takes responsibility for freeing the
708  * buffer.
709  *
710  * Returns: the buffer, or NULL on failure.
711  */
712 
gretl_print_steal_buffer(PRN * prn)713 char *gretl_print_steal_buffer (PRN *prn)
714 {
715     char *buf = NULL;
716 
717     if (prn != NULL) {
718 	buf = prn->buf;
719 	prn->buf = NULL;
720     }
721 
722     return buf;
723 }
724 
725 /**
726  * gretl_print_replace_buffer:
727  * @prn: printing struct.
728  * @buf: malloced replacement buffer.
729  *
730  * If @prn currently has a printing buffer in place,
731  * destroy the original and replace it with @buf. Note
732  * @prn "takes ownership" of @buf, which will be freed
733  * when @prn is destroyed.
734  *
735  * Returns: 0 on success, non-zero code on error.
736  */
737 
gretl_print_replace_buffer(PRN * prn,char * buf)738 int gretl_print_replace_buffer (PRN *prn, char *buf)
739 {
740     int err = 0;
741 
742     if (prn == NULL || prn->buf == NULL || buf == NULL) {
743 	err = E_DATA;
744     } else {
745 	free(prn->buf);
746 	prn->buf = buf;
747 	prn->blen = strlen(buf);
748 	prn->bufsize = prn->blen + 1;
749 	prn->savepos = -1;
750     }
751 
752     return err;
753 }
754 
755 /**
756  * gretl_print_set_save_position:
757  * @prn: printing struct.
758  *
759  * Sets the current buffer offset as the position from
760  * which a chunk of the current buffer may be saved,
761  * using gretl_print_get_chunk().
762  *
763  * Returns: 0 on success, error code if @prn is not
764  * connected to a buffer.
765  */
766 
gretl_print_set_save_position(PRN * prn)767 int gretl_print_set_save_position (PRN *prn)
768 {
769     if (prn == NULL || prn->buf == NULL) {
770 	return E_DATA;
771     } else {
772 	prn->savepos = prn->blen;
773 	return 0;
774     }
775 }
776 
777 /**
778  * gretl_print_unset_save_position:
779  * @prn: printing struct.
780  *
781  * Erases the "save position" offset as set by
782  * gretl_print_set_save_position().
783  */
784 
gretl_print_unset_save_position(PRN * prn)785 void gretl_print_unset_save_position (PRN *prn)
786 {
787     if (prn != NULL) {
788 	prn->savepos = -1;
789     }
790 }
791 
792 /**
793  * gretl_print_get_chunk:
794  * @prn: printing struct.
795  *
796  * Retrieves a copy of the buffer associated with @prn,
797  * starting at the offset from the start of the buffer
798  * as set by gretl_print_set_save_position().
799  *
800  * Returns: allocated buffer on success, or NULL on error.
801  */
802 
gretl_print_get_chunk(PRN * prn)803 char *gretl_print_get_chunk (PRN *prn)
804 {
805     int maxpos = prn->blen;
806     char *ret;
807 
808     if (prn == NULL || prn->buf == NULL ||
809 	prn->savepos < 0 || prn->savepos > maxpos) {
810 	return NULL;
811     }
812 
813     ret = gretl_strdup(prn->buf + prn->savepos);
814     prn->savepos = -1;
815 
816     return ret;
817 }
818 
819 /**
820  * gretl_print_get_chunk_at:
821  * @prn: printing struct.
822  * @pos: the byte poistion at which to start.
823  *
824  * Retrieves a copy of the buffer associated with @prn,
825  * starting at the offset from the start of the buffer
826  * specified by @pos.
827  *
828  * Returns: allocated buffer on success, or NULL on error.
829  */
830 
gretl_print_get_chunk_at(PRN * prn,int pos)831 char *gretl_print_get_chunk_at (PRN *prn, int pos)
832 {
833     int maxpos = prn->blen;
834     char *ret;
835 
836     if (prn == NULL || prn->buf == NULL ||
837 	pos < 0 || pos > maxpos) {
838 	return NULL;
839     }
840 
841     ret = gretl_strdup(prn->buf + pos);
842 
843     return ret;
844 }
845 
846 /**
847  * gretl_print_tell:
848  * @prn: printing struct.
849  *
850  * Returns: the current write position, if @prn
851  * has a buffer attached, otherwise -1.
852  */
853 
gretl_print_tell(PRN * prn)854 int gretl_print_tell (PRN *prn)
855 {
856     if (prn == NULL || prn->buf == NULL) {
857 	return -1;
858     } else {
859 	return prn->blen;
860     }
861 }
862 
set_default_csv_delim(PRN * prn)863 static void set_default_csv_delim (PRN *prn)
864 {
865     char test[4];
866 
867     sprintf(test, "%.1f", 1.0);
868 
869     if (test[1] == ',') {
870 	prn->delim = ';';
871     } else {
872 	prn->delim = ',';
873     }
874 }
875 
876 /**
877  * gretl_print_set_format:
878  * @prn: printing struct.
879  * @format: desired format code.
880  *
881  * Sets the printing format on @prn.
882  */
883 
gretl_print_set_format(PRN * prn,PrnFormat format)884 void gretl_print_set_format (PRN *prn, PrnFormat format)
885 {
886     if (prn != NULL) {
887 	if (format == GRETL_FORMAT_RTF) {
888 	    format = GRETL_FORMAT_RTF | GRETL_FORMAT_DOC;
889 	}
890 	if (format == GRETL_FORMAT_CSV) {
891 	    set_default_csv_delim(prn);
892 	}
893 	prn->format = format;
894     }
895 }
896 
897 /**
898  * gretl_print_set_delim:
899  * @prn: printing struct.
900  * @delim: desired CSV field-delimiter.
901  *
902  * Sets the CSV delimiter on @prn.
903  */
904 
gretl_print_set_delim(PRN * prn,char delim)905 void gretl_print_set_delim (PRN *prn, char delim)
906 {
907     if (prn != NULL) {
908 	prn->delim = delim;
909     }
910 }
911 
912 /**
913  * gretl_print_toggle_doc_flag:
914  * @prn: printing struct.
915  *
916  * Toggles the %GRETL_FORMAT_DOC flag on @prn.
917  */
918 
gretl_print_toggle_doc_flag(PRN * prn)919 void gretl_print_toggle_doc_flag (PRN *prn)
920 {
921     if (prn != NULL) {
922 	prn->format ^= GRETL_FORMAT_DOC;
923     }
924 }
925 
926 /**
927  * gretl_print_set_has_minus:
928  * @prn: printing struct.
929  *
930  * Sets the %GRETL_FORMAT_HAS_MINUS flag on @prn,
931  * indicating that the Unicode minus sign is
932  * supported.
933  */
934 
gretl_print_set_has_minus(PRN * prn)935 void gretl_print_set_has_minus (PRN *prn)
936 {
937     if (prn != NULL) {
938 	prn->format |= GRETL_FORMAT_HAS_MINUS;
939     }
940 }
941 
942 /**
943  * gretl_print_has_minus:
944  * @prn: printing struct.
945  *
946  * Returns: 1 if @prn supports Unicode minus sign, else 0.
947  */
948 
gretl_print_has_minus(PRN * prn)949 int gretl_print_has_minus (PRN *prn)
950 {
951     if (prn != NULL) {
952 	return (prn->format & GRETL_FORMAT_HAS_MINUS)? 1 : 0;
953     } else {
954 	return 0;
955     }
956 }
957 
realloc_prn_buffer(PRN * prn,size_t newlen)958 static int realloc_prn_buffer (PRN *prn, size_t newlen)
959 {
960     char *tmp;
961     int err = 0;
962 
963     if (newlen <= 0) {
964 	newlen = prn->bufsize * 2;
965     }
966 
967 #if PRN_DEBUG
968     fprintf(stderr, "%d bytes left\ndoing realloc(%p, %d)\n",
969 	    (int) (prn->bufsize - prn->blen), prn->buf,
970 	    (int) newlen);
971 #endif
972 
973     tmp = realloc(prn->buf, newlen);
974 
975     if (tmp == NULL) {
976 	err = 1;
977     } else {
978 	prn->bufsize = newlen;
979 	prn->buf = tmp;
980 #if PRN_DEBUG
981 	fprintf(stderr, "realloc: prn->buf is %d bytes at %p\n",
982 		(int) prn->bufsize, (void *) prn->buf);
983 #endif
984     }
985 
986     memset(prn->buf + prn->blen, 0, 1);
987 
988     return err;
989 }
990 
991 #define INIT_SIZE 2048
992 #define MINREM 1024
993 
pprintf_init(PRN * prn)994 static int pprintf_init (PRN *prn)
995 {
996     int ret = 0;
997 
998     prn->bufsize = INIT_SIZE;
999     prn->buf = malloc(prn->bufsize);
1000 
1001 #if PRN_DEBUG
1002     fprintf(stderr, "pprintf: malloc'd %d bytes at %p\n",
1003 	    (int) prn->bufsize, (void *) prn->buf);
1004 #endif
1005 
1006     if (prn->buf == NULL) {
1007 	ret = -1;
1008     } else {
1009 	memset(prn->buf, 0, 1);
1010 	prn->blen = 0;
1011     }
1012 
1013     return ret;
1014 }
1015 
get_nl_count(const char * s)1016 static int get_nl_count (const char *s)
1017 {
1018     int i, n = strlen(s) - 1;
1019     int nnl = 0;
1020 
1021     for (i=n; i>=0; i--) {
1022 	if (s[i] == '\n') nnl++;
1023 	else break;
1024     }
1025 
1026     return nnl;
1027 }
1028 
1029 /**
1030  * pprintf:
1031  * @prn: gretl printing struct.
1032  * @format: as in the C library's printf().
1033  * @Varargs: arguments to be printed.
1034  *
1035  * Multi-purpose printing function: can output to stream, to buffer
1036  * or to nowhere (silently discarding the output), depending on
1037  * how @prn was initialized.  Note that it's preferable to use
1038  * pputs() for large chunks of fixed text.
1039  *
1040  * Returns: the number of bytes printed, or -1 on memory allocation
1041  * failure.
1042  */
1043 
pprintf(PRN * prn,const char * format,...)1044 int pprintf (PRN *prn, const char *format, ...)
1045 {
1046     va_list args;
1047     int rem, plen = 0;
1048 
1049     if (prn == NULL || prn->fixed) {
1050 	return 0;
1051     }
1052 
1053     if (format != NULL && *format != '\0') {
1054 	prn->nlcount = get_nl_count(format);
1055     }
1056 
1057     if (prn->fp != NULL) {
1058 	/* printing to stream: straightforward */
1059 	va_start(args, format);
1060 	plen = vfprintf(prn->fp, format, args);
1061 	va_end(args);
1062 	return plen;
1063     } else if (prn->fz != NULL) {
1064 	gchar *tmp = NULL;
1065 
1066 	va_start(args, format);
1067 	plen = g_vasprintf(&tmp, format, args);
1068 	va_end(args);
1069 	gzputs(prn->fz, tmp);
1070 	g_free(tmp);
1071 	return plen;
1072     }
1073 
1074     if (strncmp(format, "@init", 5) == 0) {
1075 	return pprintf_init(prn);
1076     }
1077 
1078     if (prn->buf == NULL) {
1079 	return 0;
1080     }
1081 
1082     rem = prn->bufsize - prn->blen;
1083     if (rem < MINREM) {
1084 	if (realloc_prn_buffer(prn, 0)) {
1085 	    return -1;
1086 	}
1087     }
1088 
1089 #if PRN_DEBUG > 1
1090     fprintf(stderr, "printing at %p\n", (void *) (prn->buf + prn->blen));
1091 #endif
1092 
1093     /* printing to buffer: be careful not to overrun */
1094     rem = prn->bufsize - prn->blen - 1;
1095     va_start(args, format);
1096     plen = vsnprintf(prn->buf + prn->blen, rem, format, args);
1097     va_end(args);
1098 
1099     if (plen >= rem) {
1100 	/* buffer not big enough: try again */
1101 	size_t newsize = prn->bufsize + plen + 1024;
1102 
1103 	if (realloc_prn_buffer(prn, newsize)) {
1104 	    return -1;
1105 	}
1106 	rem = prn->bufsize - prn->blen - 1;
1107 	va_start(args, format);
1108 	plen = vsnprintf(prn->buf + prn->blen, rem, format, args);
1109 	va_end(args);
1110     }
1111 
1112     if (plen > 0) {
1113 	prn->blen += plen;
1114     }
1115 
1116     return plen;
1117 }
1118 
1119 /* void variant of pprintf() for use in certain callbacks */
1120 
pprintf2(PRN * prn,const char * format,...)1121 void pprintf2 (PRN *prn, const char *format, ...)
1122 {
1123     va_list args;
1124     int rem, plen = 0;
1125 
1126     if (prn == NULL || prn->fixed) {
1127 	return;
1128     }
1129 
1130     if (prn->fp != NULL) {
1131 	/* printing to stream: straightforward */
1132 	va_start(args, format);
1133 	vfprintf(prn->fp, format, args);
1134 	va_end(args);
1135 	return;
1136     }
1137 
1138     if (strncmp(format, "@init", 5) == 0) {
1139 	pprintf_init(prn);
1140 	return;
1141     }
1142 
1143     if (prn->buf == NULL) {
1144 	return;
1145     }
1146 
1147     rem = prn->bufsize - prn->blen;
1148     if (rem < MINREM) {
1149 	if (realloc_prn_buffer(prn, 0)) {
1150 	    return;
1151 	}
1152     }
1153 
1154     rem = prn->bufsize - prn->blen - 1;
1155     va_start(args, format);
1156     plen = vsnprintf(prn->buf + prn->blen, rem, format, args);
1157     va_end(args);
1158 
1159     if (plen >= rem) {
1160 	size_t newsize = prn->bufsize + plen + 1024;
1161 
1162 	if (realloc_prn_buffer(prn, newsize)) {
1163 	    return;
1164 	}
1165 	rem = prn->bufsize - prn->blen - 1;
1166 	va_start(args, format);
1167 	plen = vsnprintf(prn->buf + prn->blen, rem, format, args);
1168 	va_end(args);
1169     }
1170 
1171     if (plen > 0) {
1172 	prn->blen += plen;
1173     }
1174 }
1175 
1176 /**
1177  * pputs:
1178  * @prn: gretl printing struct.
1179  * @s: constant string to print.
1180  *
1181  * Returns: the number of bytes printed, or -1 on memory allocation
1182  * failure.
1183  */
1184 
pputs(PRN * prn,const char * s)1185 int pputs (PRN *prn, const char *s)
1186 {
1187     int slen, rem;
1188 
1189     if (prn == NULL || prn->fixed) {
1190 	return 0;
1191     }
1192 
1193     slen = strlen(s);
1194     if (slen > 0) {
1195 	prn->nlcount = get_nl_count(s);
1196     }
1197 
1198     if (prn->fp != NULL) {
1199 	fputs(s, prn->fp);
1200 	return slen;
1201     } else if (prn->fz != NULL) {
1202 	return gzputs(prn->fz, s);
1203     }
1204 
1205     if (prn->buf == NULL) {
1206 	return 0;
1207     }
1208 
1209     rem = prn->bufsize - prn->blen;
1210 
1211     while (rem < MINREM || rem <= slen) {
1212 	if (realloc_prn_buffer(prn, 0)) {
1213 	    return -1;
1214 	}
1215 	rem = prn->bufsize - prn->blen;
1216     }
1217 
1218 #if PRN_DEBUG > 1
1219     fprintf(stderr, "pputs: bufsize=%d, blen=%d, rem=%d, copying %d bytes\n",
1220 	    (int) prn->bufsize, (int) prn->blen, rem, slen);
1221 #endif
1222 
1223     strcpy(prn->buf + prn->blen, s);
1224     prn->blen += slen;
1225 
1226     return slen;
1227 }
1228 
1229 /**
1230  * pputc:
1231  * @prn: gretl printing struct.
1232  * @c: character to print
1233  *
1234  * Returns: the number of bytes printed, or -1 on memory allocation
1235  * failure.
1236  */
1237 
pputc(PRN * prn,int c)1238 int pputc (PRN *prn, int c)
1239 {
1240     if (prn == NULL || prn->fixed) {
1241 	return 0;
1242     }
1243 
1244     if (c == '\n') prn->nlcount += 1;
1245     else if (c != '\0') prn->nlcount = 0;
1246 
1247     if (prn->fp != NULL) {
1248 	fputc(c, prn->fp);
1249 	return 1;
1250     } else if (prn->fz != NULL) {
1251 	char s[2] = {c, '\0'};
1252 
1253 	return gzputs(prn->fz, s);
1254     }
1255 
1256     if (prn->buf == NULL) {
1257 	return 0;
1258     }
1259 
1260     if (prn->bufsize - prn->blen < MINREM) {
1261 	if (realloc_prn_buffer(prn, 0)) {
1262 	    return -1;
1263 	}
1264     }
1265 
1266 #if PRN_DEBUG > 1
1267     fprintf(stderr, "pputc: adding char at %p\n", (void *) (prn->buf + prn->blen));
1268 #endif
1269 
1270     prn->buf[prn->blen] = c;
1271     prn->buf[prn->blen + 1] = '\0';
1272     prn->blen += 1;
1273 
1274     return 1;
1275 }
1276 
1277 /**
1278  * gretl_prn_newline:
1279  * @prn: gretl printing struct.
1280  *
1281  * Print a line break, in the mode appropriate to the
1282  * format of @prn (plain text, TeX or RTF).
1283  */
1284 
gretl_prn_newline(PRN * prn)1285 void gretl_prn_newline (PRN *prn)
1286 {
1287     if (tex_format(prn)) {
1288 	pputs(prn, "\\\\\n");
1289     } else if (rtf_format(prn)) {
1290 	pputs(prn, "\\par\n");
1291     } else {
1292 	pputc(prn, '\n');
1293     }
1294 }
1295 
1296 /**
1297  * gretl_print_ensure_vspace:
1298  * @prn: gretl printing struct.
1299  *
1300  */
1301 
gretl_print_ensure_vspace(PRN * prn)1302 void gretl_print_ensure_vspace (PRN *prn)
1303 {
1304     if (prn != NULL && prn->nlcount < 2) {
1305 	pputc(prn, '\n');
1306     }
1307 }
1308 
1309 /**
1310  * gretl_print_flush_stream:
1311  * @prn: gretl printing struct.
1312  *
1313  * If the output of @prn is directed to a stream, flush
1314  * that stream.
1315  */
1316 
gretl_print_flush_stream(PRN * prn)1317 void gretl_print_flush_stream (PRN *prn)
1318 {
1319     if (prn != NULL) {
1320 	if (prn->fp != NULL) {
1321 	    fflush(prn->fp);
1322 	} else if (prn->fz != NULL) {
1323 	    gzflush(prn->fz, Z_SYNC_FLUSH);
1324 	}
1325     }
1326 }
1327 
1328 /**
1329  * gretl_print_close_file:
1330  * @prn: gretl printing struct.
1331  *
1332  * If the output of @prn is directed to a file, close
1333  * the file. Also frees and sets to NULL the filename
1334  * associated with the stream (but does not remove the
1335  * file).
1336  */
1337 
gretl_print_close_stream(PRN * prn)1338 void gretl_print_close_stream (PRN *prn)
1339 {
1340     if (prn == NULL) return;
1341 
1342     if (prn->fp != NULL) {
1343 	fclose(prn->fp);
1344 	prn->fp = NULL;
1345 	free(prn->fname);
1346 	prn->fname = NULL;
1347     } else if (prn->fz != NULL) {
1348 	gzclose(prn->fz);
1349 	prn->fz = NULL;
1350 	free(prn->fname);
1351 	prn->fname = NULL;
1352     }
1353 }
1354 
1355 /**
1356  * printing_to_standard_stream:
1357  * @prn: gretl printing struct.
1358  *
1359  * Returns: 1 if the output of @prn is directed to one of the
1360  * standard streams, %stdout or %stderr, else 0.
1361  */
1362 
printing_to_standard_stream(PRN * prn)1363 int printing_to_standard_stream (PRN *prn)
1364 {
1365     int ret = 0;
1366 
1367     if (prn != NULL && (prn->fp == stdout || prn->fp == stderr)) {
1368 	ret = 1;
1369     }
1370 
1371     return ret;
1372 }
1373 
prn_push_stream(PRN * prn,FILE * fp,const char * fname,const char * strvar)1374 static void prn_push_stream (PRN *prn, FILE *fp, const char *fname,
1375 			     const char *strvar)
1376 {
1377     fpinfo fi = {prn->fp, 0, NULL, NULL};
1378 
1379     if (prn->fplist == NULL) {
1380 	prn->fplist = g_array_new(FALSE, FALSE, sizeof(fpinfo));
1381     }
1382     fi.level = gretl_function_depth();
1383     if (fname != NULL) {
1384 	fi.fname = g_strdup(fname);
1385     }
1386     if (strvar != NULL) {
1387 	fi.strvar = g_strdup(strvar);
1388     }
1389     g_array_append_val(prn->fplist, fi);
1390 
1391     prn->fp = fp;
1392 }
1393 
handle_outbuf_content(FILE * fp,fpinfo * fi)1394 static int handle_outbuf_content (FILE *fp, fpinfo *fi)
1395 {
1396     user_var *uv;
1397     int err = 0;
1398 
1399     uv = get_user_var_of_type_by_name(fi->strvar,
1400 				      GRETL_TYPE_STRING);
1401     if (uv == NULL) {
1402 	err = E_DATA;
1403     } else {
1404 	char *buf = NULL;
1405 	long pos;
1406 	size_t len;
1407 
1408 	fflush(fp);
1409 	fseek(fp, 0, SEEK_END);
1410 	pos = ftell(fp);
1411 
1412 	if (pos > 0) {
1413 	    buf = calloc(pos + 1, 1);
1414 	    if (buf == NULL) {
1415 		err = E_ALLOC;
1416 	    } else {
1417 		fseek(fp, 0, SEEK_SET);
1418 		len = fread(buf, 1, pos, fp);
1419 		if (len < pos) {
1420 		    err = E_DATA;
1421 		    free(buf);
1422 		}
1423 	    }
1424 	} else {
1425 	    buf = gretl_strdup("");
1426 	}
1427 
1428 	if (!err) {
1429 	    err = user_var_replace_value(uv, buf, GRETL_TYPE_STRING);
1430 	}
1431     }
1432 
1433     return err;
1434 }
1435 
prn_pop_stream(PRN * prn)1436 static int prn_pop_stream (PRN *prn)
1437 {
1438     FILE *prev = NULL;
1439     char *strvar = NULL;
1440     int err = 0;
1441 
1442     if (prn->fplist != NULL) {
1443 	int n = prn->fplist->len;
1444 	fpinfo *fi;
1445 
1446 	if (n > 0) {
1447 	    fi = &g_array_index(prn->fplist, fpinfo, n-1);
1448 	    prev = fi->fp;
1449 	    if (fi->strvar != NULL) {
1450 		strvar = fi->strvar;
1451 		err = handle_outbuf_content(prn->fp, fi);
1452 	    }
1453 	    if (fi->fname != NULL) {
1454 		g_free(fi->fname);
1455 		fi->fname = NULL;
1456 	    }
1457 	    g_array_remove_index(prn->fplist, n-1);
1458 	}
1459     }
1460 
1461     if (prn->fp != NULL && prn->fp != stdout && prn->fp != stderr) {
1462 	fclose(prn->fp);
1463     }
1464 
1465     if (strvar != NULL) {
1466 	gchar *fname = g_strdup_printf("%s%s.prntmp",
1467 				       gretl_dotdir(),
1468 				       strvar);
1469 	gretl_remove(fname);
1470 	g_free(fname);
1471 	g_free(strvar);
1472     }
1473 
1474     prn->fp = prev;
1475 
1476     return err;
1477 }
1478 
1479 /**
1480  * print_redirection_level:
1481  * @prn: gretl printing struct.
1482  *
1483  * Returns: 0 if the output of @prn has not been redirected
1484  * relative to its original setting, else the level of
1485  * (possibly nested) redirection.
1486  */
1487 
print_redirection_level(PRN * prn)1488 int print_redirection_level (PRN *prn)
1489 {
1490     int ret = 0;
1491 
1492     if (prn != NULL) {
1493 	if (prn->fp != NULL && prn->buf != NULL) {
1494 	    ret = 1;
1495 	} else if (prn->fixed) {
1496 	    ret = 1;
1497 	}
1498 	if (prn_fp_list_active(prn)) {
1499 	    ret += prn->fplist->len; /* is this right? */
1500 	}
1501     }
1502 
1503     return ret;
1504 }
1505 
1506 /**
1507  * print_redirection_filename:
1508  * @prn: gretl printing struct.
1509  *
1510  * Returns: the name of the file to which output is currently
1511  * redirected, if applicable, otherwise NULL.
1512  */
1513 
print_redirection_filename(PRN * prn)1514 const char *print_redirection_filename (PRN *prn)
1515 {
1516     if (prn != NULL && prn_fp_list_active(prn)) {
1517 	int i = prn->fplist->len - 1;
1518 	fpinfo *fi;
1519 
1520 	fi = &g_array_index(prn->fplist, fpinfo, i);
1521 	if (fi != NULL && fi->fname != NULL) {
1522 	    return fi->fname;
1523 	}
1524     }
1525 
1526     return NULL;
1527 }
1528 
print_redirected_at_level(PRN * prn,int level)1529 int print_redirected_at_level (PRN *prn, int level)
1530 {
1531     if (prn->fplist != NULL) {
1532 	fpinfo *fi;
1533 	int i;
1534 
1535 	for (i=0; i<prn->fplist->len; i++) {
1536 	    fi = &g_array_index(prn->fplist, fpinfo, i);
1537 	    if (fi->level == level) {
1538 		return 1;
1539 	    }
1540 	}
1541     }
1542 
1543     return 0;
1544 }
1545 
1546 /**
1547  * print_start_redirection:
1548  * @prn: gretl printing struct.
1549  * @fp: stream to which output should be redirected.
1550  * @fname: name of the file or NULL.
1551  * @strvar: name of associated string variable, or NULL.
1552  *
1553  * Redirects output of @prn to @fp.
1554  *
1555  * Returns: 0 on success, 1 on error.
1556  */
1557 
print_start_redirection(PRN * prn,FILE * fp,const char * fname,const char * strvar)1558 int print_start_redirection (PRN *prn, FILE *fp,
1559 			     const char *fname,
1560 			     const char *strvar)
1561 {
1562     if (prn == NULL || prn->fixed) {
1563 	return 1;
1564     }
1565 
1566     if (prn->fp != NULL) {
1567 	/* flush the current stream */
1568 	fflush(prn->fp);
1569     }
1570     if (fp == NULL) {
1571 	/* "redirection" means just disable printing */
1572 	prn->fixed = 1;
1573     } else {
1574 	/* record current stream in prn->fplist, and
1575 	   hook output to specified stream
1576 	*/
1577 	prn_push_stream(prn, fp, fname, strvar);
1578     }
1579 
1580     return 0;
1581 }
1582 
1583 /**
1584  * print_end_redirection:
1585  * @prn: gretl printing struct.
1586  *
1587  * If the output of @prn has been diverted relative to
1588  * its original setting, terminate the redirection.
1589  *
1590  * Returns: 0 on success, 1 on error.
1591  */
1592 
print_end_redirection(PRN * prn)1593 int print_end_redirection (PRN *prn)
1594 {
1595     int err = 0;
1596 
1597     if (prn != NULL) {
1598 	if (prn->fixed) {
1599 	    prn->fixed = 0;
1600 	} else if (prn->fp != NULL) {
1601 	    err = prn_pop_stream(prn);
1602 	}
1603     } else {
1604 	err = E_DATA;
1605     }
1606 
1607     return err;
1608 }
1609 
1610 /**
1611  * plain_format:
1612  * @prn: gretl printing struct.
1613  *
1614  * Returns: 1 if the format of @prn is plain text, else 0.
1615  */
1616 
plain_format(PRN * prn)1617 int plain_format (PRN *prn)
1618 {
1619     return (prn != NULL && (prn->format & GRETL_FORMAT_TXT));
1620 }
1621 
1622 /**
1623  * rtf_format:
1624  * @prn: gretl printing struct.
1625  *
1626  * Returns: 1 if the format of @prn is RTF, else 0.
1627  */
1628 
rtf_format(PRN * prn)1629 int rtf_format (PRN *prn)
1630 {
1631     if (prn != NULL) {
1632 	if (prn->format & (GRETL_FORMAT_RTF | GRETL_FORMAT_RTF_TXT)) {
1633 	    return 1;
1634 	}
1635     }
1636 
1637     return 0;
1638 }
1639 
1640 /**
1641  * rtf_doc_format:
1642  * @prn: gretl printing struct.
1643  *
1644  * Returns: 1 if the format of @prn is RTF, and the
1645  * RTF preamble should be printed, else 0.
1646  */
1647 
rtf_doc_format(PRN * prn)1648 int rtf_doc_format (PRN *prn)
1649 {
1650     return (prn != NULL &&
1651 	    (prn->format & GRETL_FORMAT_RTF) &&
1652 	    (prn->format & GRETL_FORMAT_DOC));
1653 }
1654 
1655 /**
1656  * tex_format:
1657  * @prn: gretl printing struct.
1658  *
1659  * Returns: 1 if the format of @prn is TeX, else 0.
1660  */
1661 
tex_format(PRN * prn)1662 int tex_format (PRN *prn)
1663 {
1664     return (prn != NULL && (prn->format & GRETL_FORMAT_TEX));
1665 }
1666 
1667 /**
1668  * tex_doc_format:
1669  * @prn: gretl printing struct.
1670  *
1671  * Returns: 1 if the format of @prn is TeX and a complete
1672  * TeX document is being produced, else 0.
1673  */
1674 
tex_doc_format(PRN * prn)1675 int tex_doc_format (PRN *prn)
1676 {
1677     return (prn != NULL &&
1678 	    (prn->format & GRETL_FORMAT_TEX) &&
1679 	    (prn->format & GRETL_FORMAT_DOC));
1680 }
1681 
1682 /**
1683  * tex_eqn_format:
1684  * @prn: gretl printing struct.
1685  *
1686  * Returns: 1 if the format of @prn is TeX and a model
1687  * is being represented as an equation, rather than in
1688  * tabular form, else 0.
1689  */
1690 
tex_eqn_format(PRN * prn)1691 int tex_eqn_format (PRN *prn)
1692 {
1693     return (prn != NULL &&
1694 	    (prn->format & GRETL_FORMAT_TEX) &&
1695 	    (prn->format & GRETL_FORMAT_EQN));
1696 }
1697 
1698 /**
1699  * csv_format:
1700  * @prn: gretl printing struct.
1701  *
1702  * Returns: 1 if the format of @prn is CSV, else 0.
1703  */
1704 
csv_format(PRN * prn)1705 int csv_format (PRN *prn)
1706 {
1707     return (prn != NULL && (prn->format & GRETL_FORMAT_CSV));
1708 }
1709 
1710 /**
1711  * prn_format:
1712  * @prn: gretl printing struct.
1713  *
1714  * Returns: The formatting flags for @prn.
1715  */
1716 
prn_format(PRN * prn)1717 int prn_format (PRN *prn)
1718 {
1719     return (prn != NULL)? prn->format : 0;
1720 }
1721 
1722 /**
1723  * prn_delim:
1724  * @prn: gretl printing struct.
1725  *
1726  * Returns: The character to be used as delimiter for CSV.
1727  */
1728 
prn_delim(PRN * prn)1729 char prn_delim (PRN *prn)
1730 {
1731     return (prn != NULL)? prn->delim : ',';
1732 }
1733 
1734 /**
1735  * gretl_print_has_buffer:
1736  * @prn: gretl printing struct.
1737  *
1738  * Returns: 1 if @prn is using a buffer for printing,
1739  * otherwise 0 (e.g., if a file is being used).
1740  */
1741 
gretl_print_has_buffer(PRN * prn)1742 int gretl_print_has_buffer (PRN *prn)
1743 {
1744     return (prn != NULL && prn->buf != NULL);
1745 }
1746 
1747 /**
1748  * gretl_print_alloc:
1749  * @prn: gretl printing struct.
1750  * @s: desired size in bytes.
1751  *
1752  * If @prn is using a buffer for printing, try to
1753  * ensure that at least @s bytes are available for
1754  * further printing.  May speed things up if we
1755  * know there is a large amount of text to be
1756  * printed.
1757  *
1758  * Returns: 0 on success, non-zero on failure.
1759  */
1760 
gretl_print_alloc(PRN * prn,size_t s)1761 int gretl_print_alloc (PRN *prn, size_t s)
1762 {
1763     size_t rem;
1764     int err = 0;
1765 
1766     if (prn == NULL || prn->buf == NULL || prn->fixed) {
1767 	return E_DATA;
1768     }
1769 
1770     rem = prn->bufsize - prn->blen;
1771 
1772     if (rem <= s) {
1773 	size_t newlen = prn->blen + s + 1;
1774 	char *tmp;
1775 
1776 	tmp = realloc(prn->buf, newlen);
1777 	if (tmp == NULL) {
1778 	    err = E_ALLOC;
1779 	} else {
1780 	    prn->buf = tmp;
1781 	    prn->bufsize = newlen;
1782 	    memset(prn->buf + prn->blen, 0, 1);
1783 #if PRN_DEBUG
1784 	    fprintf(stderr, "gretl_print_alloc: realloc'd prn->buf "
1785 		    "to %d bytes\n", (int) newlen);
1786 #endif
1787 	}
1788     }
1789 
1790     return err;
1791 }
1792 
1793 /**
1794  * gretl_print_read_tempfile:
1795  * @prn: gretl printing struct.
1796  * @err: location to receive error code.
1797  *
1798  * Retrieves a copy of the content of @prn, if it takes the
1799  * form of a file that has been opened in "w+" or "a+" mode.
1800  *
1801  * Returns: allocated buffer, or NULL on failure.
1802  */
1803 
gretl_print_read_tempfile(PRN * prn,int * err)1804 char *gretl_print_read_tempfile (PRN *prn, int *err)
1805 {
1806     size_t chk, bsize;
1807     long pos0;
1808     char *buf = NULL;
1809 
1810     if (prn == NULL || prn->fp == NULL) {
1811 	fprintf(stderr, "gretl_print_read_tempfile: no temp file to read!\n");
1812 	*err = E_DATA;
1813 	return NULL;
1814     }
1815 
1816     fflush(prn->fp);
1817     pos0 = ftell(prn->fp);
1818     bsize = pos0;
1819     buf = calloc(bsize + 1, 1);
1820 
1821     if (buf == NULL) {
1822 	*err = E_ALLOC;
1823     } else {
1824 	rewind(prn->fp);
1825 	chk = fread(buf, 1, bsize, prn->fp);
1826 	if (chk != bsize) {
1827 	    fprintf(stderr, "gretl_print_read_tempfile: bsize=%d but chk=%d\n",
1828 		    (int) bsize, (int) chk);
1829 	    *err = E_DATA;
1830 	    free(buf);
1831 	    buf = NULL;
1832 	}
1833 	/* get back to where we were */
1834 	fseek(prn->fp, pos0, SEEK_SET);
1835     }
1836 
1837     return buf;
1838 }
1839