Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

gdp / ep / ep_string.c @ master

History | View | Annotate | Download (10.3 KB)

1 4e425382 Eric Allman
/* vim: set ai sw=8 sts=8 ts=8 :*/
2 0c663d10 Eric Allman
3 47c6ea64 Eric Allman
/***********************************************************************
4 055d3009 Eric Allman
**  ----- 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 6bd5476b Eric Allman
**        All rights reserved.
10 055d3009 Eric Allman
**
11 6bd5476b Eric Allman
**        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 055d3009 Eric Allman
**
17 6bd5476b Eric Allman
**        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 055d3009 Eric Allman
**
22 6bd5476b Eric Allman
**        REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
23 055d3009 Eric Allman
**        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 6bd5476b Eric Allman
**        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 055d3009 Eric Allman
**  ----- END LICENSE BLOCK -----
29 47c6ea64 Eric Allman
***********************************************************************/
30
31
#include <ep.h>
32
#include <ep_stat.h>
33
#include <ep_string.h>
34
#include <ep_pcvt.h>
35
#include <unistd.h>
36
#include <stdarg.h>
37
38
39
40
/***********************************************************************
41
**
42
**  STRLCPY, STRLCAT -- string copy/concatenate with buffer size
43
**
44
**        Some systems (e.g., Linux) still don't provide these.
45
*/
46
47
#if !EP_OSCF_HAS_STRLCPY
48
49
size_t
50
strlcpy(
51
        char *dst,
52
        const char *src,
53
        size_t n)
54
{
55
        size_t i = 0;
56
57 4e425382 Eric Allman
        if (n == 0)
58
                return 0;
59 47c6ea64 Eric Allman
        while (--n > 0 && *src != '\0')
60
        {
61
                *dst++ = *src++;
62
                i++;
63
        }
64 4e425382 Eric Allman
        *dst++ = '\0';
65 47c6ea64 Eric Allman
        if (*src != '\0')
66
                i += strlen(src);
67 4e425382 Eric Allman
        return ++i;
68 47c6ea64 Eric Allman
}
69
70
71
size_t
72
strlcat(
73
        char *dst,
74
        const char *src,
75
        size_t n)
76
{
77
        size_t i = strlen(dst);
78
79 4e425382 Eric Allman
        if (n == 0)
80
                return 0;
81 47c6ea64 Eric Allman
        while (n > 0 && *dst++ != '\0')
82
                n--;
83 3921d605 Siqi Lin
        --dst; // needed because dst points to the char after the null terminator
84 47c6ea64 Eric Allman
        while (*src != '\0' && --n > 0)
85
        {
86
                *dst++ = *src++;
87
                i++;
88
        }
89
        if (*src != '\0')
90
                i += strlen(src);
91 4e425382 Eric Allman
        *dst++ = '\0';
92
        return ++i;
93 47c6ea64 Eric Allman
}
94
95
#endif /* EP_OSCF_HAS_STRLCPY */
96
97
98
/***********************************************************************
99
**
100
**  EP_STR_LCPYN -- copy and concatenate N strings
101
**
102
**        Parameters:
103
**                dst -- destination pointer.
104
**                siz -- size of space available at dst.
105 9e55d093 Eric Allman
**                ... -- a NULL terminated list of strings to copy to dst.
106 47c6ea64 Eric Allman
**
107
**        Returns:
108
**                The number of bytes that would have been copied if dst
109
**                were large enough.
110
*/
111
112
// helper routine really for internal use only.  Could be exposed if needed.
113
size_t
114
ep_str_vlcpyn(
115
        char *dst,
116
        size_t siz,
117
        va_list av)
118
{
119
        size_t asize = 0;                // actual size
120 9e55d093 Eric Allman
        char *p = NULL;
121 47c6ea64 Eric Allman
122
        if (siz <= 0)
123
                return siz;                // no room for anything
124
125 9e55d093 Eric Allman
        siz--;                                // allow for NULL byte at end
126
        while (siz > 0 && (p = va_arg(av, char *)) != NULL)
127 47c6ea64 Eric Allman
        {
128
                while (siz-- > 0 && (*dst = *p++) != '\0')
129
                        dst++, asize++;
130
        }
131
        *dst = '\0';
132
133
        // see if we fit
134 9e55d093 Eric Allman
        if (p != NULL)
135 47c6ea64 Eric Allman
        {
136
                // buffer has overflowed; just count the rest
137
138
                // first any residual in the current string
139
                while (*p++ != '\0')
140
                        asize++;
141
142
                // then future strings
143 9e55d093 Eric Allman
                while ((p = va_arg(av, char *)) != NULL)
144 47c6ea64 Eric Allman
                        asize += strlen(p);
145
        }
146
147
        return asize;
148
}
149
150
size_t
151
ep_str_lcpyn(
152
        char *dst,
153
        size_t siz,
154
        ...)
155
{
156
        va_list av;
157
        size_t asize;                        // actual size
158
159
        va_start(av, siz);
160
        asize = ep_str_vlcpyn(dst, siz, av);
161
        va_end(av);
162
163
        return asize;
164
}
165
166
167
/***********************************************************************
168
**
169
**  EP_STR_LCATN -- copy and concatenate N strings to existing string
170
**
171
**        Parameters:
172
**                dst -- destination pointer.
173
**                siz -- size of space available at dst.
174 9e55d093 Eric Allman
**                ... -- a NULL terminated list of strings to copy to dst.
175 47c6ea64 Eric Allman
**
176
**        Returns:
177
**                The number of bytes that would have been copied if dst
178
**                were large enough.
179
*/
180
181
size_t
182
ep_str_lcatn(
183
        char *dst,
184
        size_t siz,
185
        ...)
186
{
187
        va_list av;
188
        size_t i = strlen(dst);
189
190
        va_start(av, siz);
191
        i += ep_str_vlcpyn(dst + i, siz - i, av);
192
        va_end(av);
193
194
        return i;
195
}
196
197
198
/***********************************************************************
199
**
200
**  Video escape sequences.  Should be setable.
201
*/
202
203
// ANSI X3.64
204
struct epVidSequences        EpVidANSI_X3_64 =
205
{
206
        .vidnorm =        "\033[0m",        // video normal
207
        .vidbold =        "\033[1m",        // video bold
208
        .vidfaint =        "\033[2m",        // video faint
209
        .vidstout =        "\033[3m",        // video standout
210
        .viduline =        "\033[4m",        // video underline
211
        .vidblink =        "\033[5m",        // video blink (ugh)
212
        .vidinv =        "\033[7m",        // video invert
213
        .vidfgblack =        "\033[30m",        // video foreground black
214
        .vidfgred =        "\033[31m",        // video foreground red
215
        .vidfggreen =        "\033[32m",        // video foreground green
216
        .vidfgyellow =        "\033[33m",        // video foreground yellow
217
        .vidfgblue =        "\033[34m",        // video foreground blue
218
        .vidfgmagenta =        "\033[35m",        // video foreground magenta
219
        .vidfgcyan =        "\033[36m",        // video foreground cyan
220
        .vidfgwhite =        "\033[37m",        // video foreground white
221
        .vidbgblack =        "\033[40m",        // video background black
222
        .vidbgred =        "\033[41m",        // video background red
223
        .vidbggreen =        "\033[42m",        // video background green
224
        .vidbgyellow =        "\033[43m",        // video background yellow
225
        .vidbgblue =        "\033[44m",        // video background blue
226
        .vidbgmagenta =        "\033[45m",        // video background magenta
227
        .vidbgcyan =        "\033[46m",        // video background cyan
228
        .vidbgwhite =        "\033[47m",        // video background white
229
};
230
231
// none
232
struct epVidSequences        EpVidNull =
233
{
234
        .vidnorm =        "",                // video normal
235
        .vidbold =        "",                // video bold
236
        .vidfaint =        "",                // video faint
237
        .vidstout =        "",                // video standout
238
        .viduline =        "",                // video underline
239
        .vidblink =        "",                // video blink (ugh)
240
        .vidinv =        "",                // video invert
241
        .vidfgblack =        "",                // video foreground black
242
        .vidfgred =        "",                // video foreground red
243
        .vidfggreen =        "",                // video foreground green
244
        .vidfgyellow =        "",                // video foreground yellow
245
        .vidfgblue =        "",                // video foreground blue
246
        .vidfgmagenta =        "",                // video foreground magenta
247
        .vidfgcyan =        "",                // video foreground cyan
248
        .vidfgwhite =        "",                // video foreground white
249
        .vidbgblack =        "",                // video background black
250
        .vidbgred =        "",                // video background red
251
        .vidbggreen =        "",                // video background green
252
        .vidbgyellow =        "",                // video background yellow
253
        .vidbgblue =        "",                // video background blue
254
        .vidbgmagenta =        "",                // video background magenta
255
        .vidbgcyan =        "",                // video background cyan
256
        .vidbgwhite =        "",                // video background white
257
};
258
259 7cef6663 Eric Allman
struct epVidSequences        *EpVid = &EpVidNull;
260 47c6ea64 Eric Allman
261
262
/***********************************************************************
263
**
264
**  EP_STR_VID_SET -- set the desired video sequence
265
**
266
**        Parameters:
267
**                type -- the type of sequence to use, either "ansi" or
268
**                        "none"
269
**
270
**        Returns:
271
**                status code
272
**
273
**        Side Effects:
274
**                Updates the binding of 'EpVid'
275
*/
276
277
EP_STAT
278
ep_str_vid_set(
279
        const char *type)
280
{
281
        if (type == NULL)
282 7cef6663 Eric Allman
                type = getenv("EP_TERM");
283
        if (type == NULL)
284 47c6ea64 Eric Allman
        {
285
                // try to guess based on environment
286
                if (isatty(1))
287
                {
288 7cef6663 Eric Allman
                        type = getenv("TERM");
289 0decb227 Eric Allman
                        if (type != NULL &&
290
                            (strncmp(type, "xterm", 5) == 0 ||
291
                             strncmp(type, "ansi", 4) == 0))
292 47c6ea64 Eric Allman
                                EpVid = &EpVidANSI_X3_64;
293
                }
294
                return EP_STAT_OK;
295
        }
296
297
        if (strcasecmp(type, "none") == 0)
298
        {
299
                EpVid = &EpVidNull;
300
        }
301
        else if (strcasecmp(type, "ansi") == 0)
302
        {
303
                EpVid = &EpVidANSI_X3_64;
304
        }
305
        else
306
        {
307
                char e1buf[64];
308
309 7cef6663 Eric Allman
                fprintf(stderr, "ep_str_vid_set: video type `%s' not valid\n",
310 47c6ea64 Eric Allman
                        ep_pcvt_str(e1buf, sizeof e1buf, type));
311
                return EP_STAT_ERROR;
312
        }
313
        return EP_STAT_OK;
314
}
315
316
317
318
/***********************************************************************
319
**
320
**  Special characters used internally that may vary by locale.
321
**  This is not intended to be complete; it's really for internal
322
**  use only.
323
*/
324
325
// US-ASCII
326
struct epCharSequences        EpCharASCII =
327
{
328
        .lquote =        "`",                // lquote
329
        .rquote =        "'",                // rquote
330
        .copyright =        "(c)",                // copyright
331
        .degree =        "deg",                // degree
332
        .micro =        "u",                // micro
333 07eaf217 Eric Allman
        .plusminus =        "+/-",                // plus-or-minus
334
        .times =        "*",                // times
335
        .divide =        "/",                // divide
336
        .null =                "NULL",                // null
337
        .notequal =        "!=",                // not equal
338 1970c565 Eric Allman
        .unprintable =        "?",                // sub for unprintable
339 064de711 Eric Allman
        .paragraph =        "pp.",
340
        .section =        "sec.",                // section
341
        .notsign =        "(not)",        // "not" symbol
342
        .infinity =        "(inf)",
343 47c6ea64 Eric Allman
};
344
345
// ISO 8859-1:1987
346
struct epCharSequences        EpCharISO_8859_1 =
347
{
348 07eaf217 Eric Allman
        .lquote =        "\xAB",                // << character
349
        .rquote =        "\xBB",                // >> character
350
        .copyright =        "\xA9",
351
        .degree =        "\xB0",
352
        .micro =        "\xB5",
353
        .plusminus =        "\xB1",
354
        .times =        "\xD7",
355
        .divide =        "\xF7",
356
        .null =                "\xD8",
357
        .notequal =        "!=",
358 064de711 Eric Allman
        .unprintable =        "\xA4",                // generic currency symbol
359
        .paragraph =        "\xB6",
360
        .section =        "\xA7",
361
        .notsign =        "\xAC",
362
        .infinity =        "(inf)",
363 47c6ea64 Eric Allman
};
364
365
// Unicode UTF-8 (US conventions)
366
struct epCharSequences        EpCharUTF_8 =
367
{
368 07eaf217 Eric Allman
        .lquote =        "\xC2\xAB",        // '<<' character U+00AB, 0xC2 AB
369
        .rquote =        "\xC2\xBB",        // '>>' character U+00BB, 0xC2 BB
370
        .copyright =        "\xC2\xA9",        // U+00A9, 0xC2 A9
371
        .degree =        "\xC2\xB0",        // U+00B0
372
        .micro =        "\xC2\xB5",        // U+00B5
373 14aa795e Eric Allman
        .plusminus =        "\xC2\xB1",        // U+00B1, 0xC2 B1
374 07eaf217 Eric Allman
        .times =        "\xC3\x97",        // U+00D7
375
        .divide =        "\xC3\xB7",        // U+00F7
376
        .null =                "\xE2\x88\x85",        // U+2205
377
        .notequal =        "\xE2\x89\xA0",        // U+2260
378 1eae4944 Eric Allman
        .unprintable =        "\xE2\x8C\xA7",        // U+2327, "X" in a box
379
//        .unprintable =        "\xE2\x8D\xB0",        // U+2370, question mark in a box
380 064de711 Eric Allman
        .paragraph =        "\xC2\xB6",        // U+00B6
381
        .section =        "\xC2\xA7",        // U+00A7
382
        .notsign =        "\xC2\xAC",        // U+00AC
383
        .infinity =        "\xE2\x88\x9E",        // U+221E
384 47c6ea64 Eric Allman
};
385
386 7cef6663 Eric Allman
struct epCharSequences        *EpChar = &EpCharASCII;
387 47c6ea64 Eric Allman
388
389
/***********************************************************************
390
**
391
**  EP_STR_CHAR_SET -- set the desired character set sequences
392
**
393
**        Parameters:
394
**                type -- the type of sequence to use, one of
395
**                        "ascii", "iso-8859-1", or "utf-8"
396
**
397
**        Returns:
398
**                status code
399
**
400
**        Side Effects:
401
**                Updates the binding of 'EpChar'
402
*/
403
404
EP_STAT
405
ep_str_char_set(
406
        const char *type)
407
{
408
        if (type == NULL)
409
        {
410
                // try to guess based on environment
411 58292089 Eric Allman
                const char *p;
412 47c6ea64 Eric Allman
413
                if (!isatty(1))
414
                        return EP_STAT_OK;
415
416
                type = getenv("LANG");
417
                if (type == NULL)
418
                        return EP_STAT_OK;
419
                p = strrchr(type, '.');
420
                if (p != NULL)
421
                        type = ++p;
422
        }
423
424 0d5b0de2 Eric Allman
        if (strcasecmp(type, "iso-8859-1") == 0 ||
425 47c6ea64 Eric Allman
                 strcasecmp(type, "iso-latin-1") == 0)
426
        {
427
                EpChar = &EpCharISO_8859_1;
428
        }
429
        else if (strcasecmp(type, "utf-8") == 0 ||
430 d817b4c2 Eric Allman
                 strcasecmp(type, "utf_8") == 0 ||
431 47c6ea64 Eric Allman
                 strcasecmp(type, "utf8") == 0)
432
        {
433
                EpChar = &EpCharUTF_8;
434
        }
435
        else
436
        {
437 d817b4c2 Eric Allman
                EpChar = &EpCharASCII;
438 47c6ea64 Eric Allman
        }
439
        return EP_STAT_OK;
440
}