/src/util-linux/include/carefulputc.h
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef UTIL_LINUX_CAREFULPUTC_H |
2 | | #define UTIL_LINUX_CAREFULPUTC_H |
3 | | |
4 | | #include <stdio.h> |
5 | | #include <string.h> |
6 | | #include <ctype.h> |
7 | | #include <stdbool.h> |
8 | | |
9 | | #include "widechar.h" |
10 | | #include "cctype.h" |
11 | | |
12 | | /* |
13 | | * A puts() for use in write and wall (that sometimes are sgid tty). |
14 | | * It avoids control and invalid characters. |
15 | | * The locale of the recipient is nominally unknown, |
16 | | * but it's a solid bet that it's compatible with the author's. |
17 | | * Use soft_width=0 to disable wrapping. |
18 | | */ |
19 | | static inline int fputs_careful(const char * s, FILE *fp, const char ctrl, bool cr_lf, int soft_width) |
20 | 21.5k | { |
21 | 21.5k | int ret = 0, col = 0; |
22 | | |
23 | 194k | for (size_t slen = strlen(s); *s; ++s, --slen) { |
24 | 172k | if (*s == '\t') |
25 | 664 | col += (7 - (col % 8)) - 1; |
26 | 172k | else if (*s == '\r') |
27 | 3.66k | col = -1; |
28 | 168k | else if (*s == '\a') |
29 | 562 | --col; |
30 | | |
31 | 172k | if ((soft_width && col >= soft_width) || *s == '\n') { |
32 | 22.0k | if (soft_width) { |
33 | 0 | fprintf(fp, "%*s", soft_width - col, ""); |
34 | 0 | col = 0; |
35 | 0 | } |
36 | 22.0k | ret = fputs(cr_lf ? "\r\n" : "\n", fp); |
37 | 22.0k | if (*s == '\n' || ret < 0) |
38 | 22.0k | goto wrote; |
39 | 22.0k | } |
40 | | |
41 | 150k | if (isprint(*s) || *s == '\a' || *s == '\t' || *s == '\r') { |
42 | 62.1k | ret = putc(*s, fp); |
43 | 62.1k | ++col; |
44 | 88.5k | } else if (!c_isascii(*s)) { |
45 | 58.3k | #ifdef HAVE_WIDECHAR |
46 | 58.3k | wchar_t w; |
47 | 58.3k | size_t clen = mbtowc(&w, s, slen); |
48 | 58.3k | switch(clen) { |
49 | 0 | case (size_t)-2: // incomplete |
50 | 58.3k | case (size_t)-1: // EILSEQ |
51 | 58.3k | mbtowc(NULL, NULL, 0); |
52 | 58.3k | nonprint: |
53 | 58.3k | col += ret = fprintf(fp, "\\%3hho", *s); |
54 | 58.3k | break; |
55 | 0 | default: |
56 | 0 | if(!iswprint(w)) |
57 | 0 | goto nonprint; |
58 | 0 | ret = fwrite(s, 1, clen, fp); |
59 | 0 | if (soft_width) |
60 | 0 | col += wcwidth(w); |
61 | 0 | s += clen - 1; |
62 | 0 | slen -= clen - 1; |
63 | 0 | break; |
64 | 58.3k | } |
65 | | #else |
66 | | col += ret = fprintf(fp, "\\%3hho", *s); |
67 | | #endif |
68 | 58.3k | } else { |
69 | 30.2k | ret = fputs((char[]){ ctrl, *s ^ 0x40, '\0' }, fp); |
70 | 30.2k | col += 2; |
71 | 30.2k | } |
72 | | |
73 | 172k | wrote: |
74 | 172k | if (ret < 0) |
75 | 0 | return EOF; |
76 | 172k | } |
77 | 21.5k | return 0; |
78 | 21.5k | } Line | Count | Source | 20 | 21.5k | { | 21 | 21.5k | int ret = 0, col = 0; | 22 | | | 23 | 194k | for (size_t slen = strlen(s); *s; ++s, --slen) { | 24 | 172k | if (*s == '\t') | 25 | 664 | col += (7 - (col % 8)) - 1; | 26 | 172k | else if (*s == '\r') | 27 | 3.66k | col = -1; | 28 | 168k | else if (*s == '\a') | 29 | 562 | --col; | 30 | | | 31 | 172k | if ((soft_width && col >= soft_width) || *s == '\n') { | 32 | 22.0k | if (soft_width) { | 33 | 0 | fprintf(fp, "%*s", soft_width - col, ""); | 34 | 0 | col = 0; | 35 | 0 | } | 36 | 22.0k | ret = fputs(cr_lf ? "\r\n" : "\n", fp); | 37 | 22.0k | if (*s == '\n' || ret < 0) | 38 | 22.0k | goto wrote; | 39 | 22.0k | } | 40 | | | 41 | 150k | if (isprint(*s) || *s == '\a' || *s == '\t' || *s == '\r') { | 42 | 62.1k | ret = putc(*s, fp); | 43 | 62.1k | ++col; | 44 | 88.5k | } else if (!c_isascii(*s)) { | 45 | 58.3k | #ifdef HAVE_WIDECHAR | 46 | 58.3k | wchar_t w; | 47 | 58.3k | size_t clen = mbtowc(&w, s, slen); | 48 | 58.3k | switch(clen) { | 49 | 0 | case (size_t)-2: // incomplete | 50 | 58.3k | case (size_t)-1: // EILSEQ | 51 | 58.3k | mbtowc(NULL, NULL, 0); | 52 | 58.3k | nonprint: | 53 | 58.3k | col += ret = fprintf(fp, "\\%3hho", *s); | 54 | 58.3k | break; | 55 | 0 | default: | 56 | 0 | if(!iswprint(w)) | 57 | 0 | goto nonprint; | 58 | 0 | ret = fwrite(s, 1, clen, fp); | 59 | 0 | if (soft_width) | 60 | 0 | col += wcwidth(w); | 61 | 0 | s += clen - 1; | 62 | 0 | slen -= clen - 1; | 63 | 0 | break; | 64 | 58.3k | } | 65 | | #else | 66 | | col += ret = fprintf(fp, "\\%3hho", *s); | 67 | | #endif | 68 | 58.3k | } else { | 69 | 30.2k | ret = fputs((char[]){ ctrl, *s ^ 0x40, '\0' }, fp); | 70 | 30.2k | col += 2; | 71 | 30.2k | } | 72 | | | 73 | 172k | wrote: | 74 | 172k | if (ret < 0) | 75 | 0 | return EOF; | 76 | 172k | } | 77 | 21.5k | return 0; | 78 | 21.5k | } |
Unexecuted instantiation: script.c:fputs_careful |
79 | | |
80 | | static inline void fputs_quoted_case(const char *data, FILE *out, int dir) |
81 | 391 | { |
82 | 391 | const char *p; |
83 | | |
84 | 391 | fputc('"', out); |
85 | 19.5k | for (p = data; p && *p; p++) { |
86 | 19.1k | if ((unsigned char) *p == 0x22 || /* " */ |
87 | 19.1k | (unsigned char) *p == 0x5c || /* \ */ |
88 | 19.1k | (unsigned char) *p == 0x60 || /* ` */ |
89 | 19.1k | (unsigned char) *p == 0x24 || /* $ */ |
90 | 19.1k | !isprint((unsigned char) *p) || |
91 | 19.1k | iscntrl((unsigned char) *p)) { |
92 | | |
93 | 10.5k | fprintf(out, "\\x%02x", (unsigned char) *p); |
94 | 10.5k | } else |
95 | 8.64k | fputc(dir == 1 ? toupper(*p) : |
96 | 8.64k | dir == -1 ? tolower(*p) : |
97 | 8.64k | *p, out); |
98 | 19.1k | } |
99 | 391 | fputc('"', out); |
100 | 391 | } Unexecuted instantiation: last.c:fputs_quoted_case script.c:fputs_quoted_case Line | Count | Source | 81 | 391 | { | 82 | 391 | const char *p; | 83 | | | 84 | 391 | fputc('"', out); | 85 | 19.5k | for (p = data; p && *p; p++) { | 86 | 19.1k | if ((unsigned char) *p == 0x22 || /* " */ | 87 | 19.1k | (unsigned char) *p == 0x5c || /* \ */ | 88 | 19.1k | (unsigned char) *p == 0x60 || /* ` */ | 89 | 19.1k | (unsigned char) *p == 0x24 || /* $ */ | 90 | 19.1k | !isprint((unsigned char) *p) || | 91 | 19.1k | iscntrl((unsigned char) *p)) { | 92 | | | 93 | 10.5k | fprintf(out, "\\x%02x", (unsigned char) *p); | 94 | 10.5k | } else | 95 | 8.64k | fputc(dir == 1 ? toupper(*p) : | 96 | 8.64k | dir == -1 ? tolower(*p) : | 97 | 8.64k | *p, out); | 98 | 19.1k | } | 99 | 391 | fputc('"', out); | 100 | 391 | } |
|
101 | | |
102 | 391 | #define fputs_quoted(_d, _o) fputs_quoted_case(_d, _o, 0) |
103 | | #define fputs_quoted_upper(_d, _o) fputs_quoted_case(_d, _o, 1) |
104 | | #define fputs_quoted_lower(_d, _o) fputs_quoted_case(_d, _o, -1) |
105 | | |
106 | | static inline void fputs_nonblank(const char *data, FILE *out) |
107 | 0 | { |
108 | 0 | const char *p; |
109 | 0 |
|
110 | 0 | for (p = data; p && *p; p++) { |
111 | 0 | if (isblank((unsigned char) *p) || |
112 | 0 | (unsigned char) *p == 0x5c || /* \ */ |
113 | 0 | !isprint((unsigned char) *p) || |
114 | 0 | iscntrl((unsigned char) *p)) { |
115 | 0 |
|
116 | 0 | fprintf(out, "\\x%02x", (unsigned char) *p); |
117 | 0 |
|
118 | 0 | } else |
119 | 0 | fputc(*p, out); |
120 | 0 | } |
121 | 0 | } Unexecuted instantiation: last.c:fputs_nonblank Unexecuted instantiation: script.c:fputs_nonblank |
122 | | |
123 | | #endif /* _CAREFULPUTC_H */ |