Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

gdp / ep / ep_fopen_styled.c @ master

History | View | Annotate | Download (3.72 KB)

1 355109e1 Eric Allman
/* vim: set ai sw=8 sts=8 ts=8 :*/
2
3
/***********************************************************************
4
**  ----- BEGIN LICENSE BLOCK -----
5
**        LIBEP: Enhanced Portability Library (Reduced Edition)
6
**
7 c87dd166 Eric Allman
**        Copyright (c) 2008-2019, Eric P. Allman.  All rights reserved.
8
**        Copyright (c) 2015-2019, Regents of the University of California.
9 355109e1 Eric Allman
**        All rights reserved.
10
**
11
**        Permission is hereby granted, without written agreement and without
12
**        license or royalty fees, to use, copy, modify, and distribute this
13
**        software and its documentation for any purpose, provided that the above
14
**        copyright notice and the following two paragraphs appear in all copies
15
**        of this software.
16
**
17
**        IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
18
**        SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
19
**        PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
20
**        EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21
**
22
**        REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
23
**        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24
**        FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION,
25
**        IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO
26
**        OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
27
**        OR MODIFICATIONS.
28
**  ----- END LICENSE BLOCK -----
29
***********************************************************************/
30
31
/*
32
**  Open up a stream that has styling (e.g., colors or fonts)
33
**
34
**        This is a wrapper around funopen (on BSD and MacOS) or
35
**        fopencookie (on Linux).  These two routimes do substantially
36
**        the same thing.
37
*/
38
39
#if __FreeBSD__ || __APPLE__
40
#   define IORESULT_T        int
41
#   define IOBLOCK_T        int
42
#elif __linux__
43
#   define IORESULT_T        ssize_t
44
#   define IOBLOCK_T        size_t
45
#   define _GNU_SOURCE        1        // required to get fopencookie
46
#else
47
#   error Cannot determine use of funopen vs fopencookie
48
#endif
49
50
#include <ep.h>
51
#include <string.h>
52
#include <stdio.h>
53
#include <sys/errno.h>
54
55
struct styleinfo
56
{
57
        FILE        *underlying;        // underlying file
58
        char        *so;                // "shift out" string
59
        char        *si;                // "shift in" string
60
};
61
62
static IORESULT_T
63
styled_write(void *cookie, const char *buf, IOBLOCK_T size)
64
{
65
        struct styleinfo *sinf = (struct styleinfo *) cookie;
66 1261c259 Eric Allman
        IORESULT_T result = 0;
67 355109e1 Eric Allman
68
        flockfile(sinf->underlying);
69 1261c259 Eric Allman
        while (size > 0)
70
        {
71
                const char *p;
72
                IOBLOCK_T tlen;
73
74
                tlen = size;
75
                p = memchr(buf, '\n', tlen);
76
                if (p != NULL)
77
                        tlen = p - buf;
78
                if (tlen > 0)
79
                {
80
                        IORESULT_T tres;
81
                        if (sinf->so != NULL)
82
                                fputs(sinf->so, sinf->underlying);
83
                        tres = fwrite(buf, 1, tlen, sinf->underlying);
84
                        if (sinf->si != NULL)
85
                                fputs(sinf->si, sinf->underlying);
86
                        buf += tlen;
87
                        size -= tlen;
88
                        if (tres > 0)
89
                                result += tres;
90
                }
91
                if (size > 0 && *buf == '\n')
92
                {
93
                        fputc(*buf++, sinf->underlying);
94
                        result++;
95
                        size--;
96
                }
97
        }
98 355109e1 Eric Allman
        funlockfile(sinf->underlying);
99 1261c259 Eric Allman
        fflush(sinf->underlying);
100 ac10a316 Eric Allman
        return result;
101 355109e1 Eric Allman
}
102
103
static int
104
styled_close(void *cookie)
105
{
106
        struct styleinfo *sinf = (struct styleinfo *) cookie;
107
108
        if (sinf->so != NULL)
109
                ep_mem_free(sinf->so);
110
        if (sinf->si != NULL)
111
                ep_mem_free(sinf->si);
112
        ep_mem_free(cookie);
113
        return 0;
114
}
115
116
117
FILE *
118
ep_fopen_styled(FILE *underlying,
119
                const char *so,
120
                const char *si)
121
{
122 ac10a316 Eric Allman
        FILE *fp;
123 355109e1 Eric Allman
        struct styleinfo *sinf = (struct styleinfo *) ep_mem_zalloc(sizeof *sinf);
124
        if (sinf == NULL)
125
                return NULL;
126
        sinf->underlying = underlying;
127
        if (so != NULL)
128
                sinf->so = strdup(so);
129
        if (si != NULL)
130
                sinf->si = strdup(si);
131
132
#if __FreeBSD__ || __APPLE__
133
        {
134
                // BSD/MacOS
135 ac10a316 Eric Allman
                fp = funopen(sinf, NULL, &styled_write, NULL, &styled_close);
136 355109e1 Eric Allman
        }
137
#elif __linux__
138
        {
139
                // Linux
140
                cookie_io_functions_t iof =
141
                {
142
                        NULL,
143
                        &styled_write,
144
                        NULL,
145
                        &styled_close
146
                };
147 ac10a316 Eric Allman
                fp = fopencookie(sinf, "w", iof);
148 355109e1 Eric Allman
        }
149
#endif
150 ac10a316 Eric Allman
        setlinebuf(fp);
151
        return fp;
152 355109e1 Eric Allman
}