/src/util-linux/include/carefulputc.h
Line | Count | Source |
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 | 22.3k | { |
21 | 22.3k | int ret = 0, col = 0; |
22 | | |
23 | 201k | for (size_t slen = strlen(s); *s; ++s, --slen) { |
24 | 179k | if (*s == '\t') |
25 | 660 | col += (7 - (col % 8)) - 1; |
26 | 178k | else if (*s == '\r') |
27 | 3.95k | col = -1; |
28 | 174k | else if (*s == '\a') |
29 | 903 | --col; |
30 | | |
31 | 179k | if ((soft_width && col >= soft_width) || *s == '\n') { |
32 | 23.1k | if (soft_width) { |
33 | 0 | fprintf(fp, "%*s", soft_width - col, ""); |
34 | 0 | col = 0; |
35 | 0 | } |
36 | 23.1k | ret = fputs(cr_lf ? "\r\n" : "\n", fp); |
37 | 23.1k | if (*s == '\n' || ret < 0) |
38 | 23.1k | goto wrote; |
39 | 23.1k | } |
40 | | |
41 | 156k | if (isprint(*s) || *s == '\a' || *s == '\t' || *s == '\r') { |
42 | 67.3k | ret = putc(*s, fp); |
43 | 67.3k | ++col; |
44 | 88.9k | } else if (!c_isascii(*s)) { |
45 | 57.4k | #ifdef HAVE_WIDECHAR |
46 | 57.4k | wchar_t w; |
47 | 57.4k | size_t clen = mbtowc(&w, s, slen); |
48 | 57.4k | switch(clen) { |
49 | 0 | case (size_t)-2: // incomplete |
50 | 57.4k | case (size_t)-1: // EILSEQ |
51 | 57.4k | mbtowc(NULL, NULL, 0); |
52 | 57.4k | nonprint: |
53 | 57.4k | col += ret = fprintf(fp, "\\%3hho", *s); |
54 | 57.4k | 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 | 57.4k | } |
65 | | #else |
66 | | col += ret = fprintf(fp, "\\%3hho", *s); |
67 | | #endif |
68 | 57.4k | } else { |
69 | 31.5k | ret = fputs((char[]){ ctrl, *s ^ 0x40, '\0' }, fp); |
70 | 31.5k | col += 2; |
71 | 31.5k | } |
72 | | |
73 | 179k | wrote: |
74 | 179k | if (ret < 0) |
75 | 0 | return EOF; |
76 | 179k | } |
77 | 22.3k | return 0; |
78 | 22.3k | } Line | Count | Source | 20 | 22.3k | { | 21 | 22.3k | int ret = 0, col = 0; | 22 | | | 23 | 201k | for (size_t slen = strlen(s); *s; ++s, --slen) { | 24 | 179k | if (*s == '\t') | 25 | 660 | col += (7 - (col % 8)) - 1; | 26 | 178k | else if (*s == '\r') | 27 | 3.95k | col = -1; | 28 | 174k | else if (*s == '\a') | 29 | 903 | --col; | 30 | | | 31 | 179k | if ((soft_width && col >= soft_width) || *s == '\n') { | 32 | 23.1k | if (soft_width) { | 33 | 0 | fprintf(fp, "%*s", soft_width - col, ""); | 34 | 0 | col = 0; | 35 | 0 | } | 36 | 23.1k | ret = fputs(cr_lf ? "\r\n" : "\n", fp); | 37 | 23.1k | if (*s == '\n' || ret < 0) | 38 | 23.1k | goto wrote; | 39 | 23.1k | } | 40 | | | 41 | 156k | if (isprint(*s) || *s == '\a' || *s == '\t' || *s == '\r') { | 42 | 67.3k | ret = putc(*s, fp); | 43 | 67.3k | ++col; | 44 | 88.9k | } else if (!c_isascii(*s)) { | 45 | 57.4k | #ifdef HAVE_WIDECHAR | 46 | 57.4k | wchar_t w; | 47 | 57.4k | size_t clen = mbtowc(&w, s, slen); | 48 | 57.4k | switch(clen) { | 49 | 0 | case (size_t)-2: // incomplete | 50 | 57.4k | case (size_t)-1: // EILSEQ | 51 | 57.4k | mbtowc(NULL, NULL, 0); | 52 | 57.4k | nonprint: | 53 | 57.4k | col += ret = fprintf(fp, "\\%3hho", *s); | 54 | 57.4k | 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 | 57.4k | } | 65 | | #else | 66 | | col += ret = fprintf(fp, "\\%3hho", *s); | 67 | | #endif | 68 | 57.4k | } else { | 69 | 31.5k | ret = fputs((char[]){ ctrl, *s ^ 0x40, '\0' }, fp); | 70 | 31.5k | col += 2; | 71 | 31.5k | } | 72 | | | 73 | 179k | wrote: | 74 | 179k | if (ret < 0) | 75 | 0 | return EOF; | 76 | 179k | } | 77 | 22.3k | return 0; | 78 | 22.3k | } |
Unexecuted instantiation: script.c:fputs_careful |
79 | | |
80 | | static inline void fputs_quoted_case(const char *data, FILE *out, int dir) |
81 | 751 | { |
82 | 751 | const char *p; |
83 | | |
84 | 751 | fputc('"', out); |
85 | 18.5k | for (p = data; p && *p; p++) { |
86 | 17.8k | if ((unsigned char) *p == 0x22 || /* " */ |
87 | 17.5k | (unsigned char) *p == 0x5c || /* \ */ |
88 | 8.91k | (unsigned char) *p == 0x60 || /* ` */ |
89 | 8.63k | (unsigned char) *p == 0x24 || /* $ */ |
90 | 8.44k | !isprint((unsigned char) *p) || |
91 | 17.8k | iscntrl((unsigned char) *p)) { |
92 | | |
93 | 13.3k | fprintf(out, "\\x%02x", (unsigned char) *p); |
94 | 13.3k | } else |
95 | 4.53k | fputc(dir == 1 ? toupper(*p) : |
96 | 4.53k | dir == -1 ? tolower(*p) : |
97 | 4.53k | *p, out); |
98 | 17.8k | } |
99 | 751 | fputc('"', out); |
100 | 751 | } Unexecuted instantiation: last.c:fputs_quoted_case script.c:fputs_quoted_case Line | Count | Source | 81 | 751 | { | 82 | 751 | const char *p; | 83 | | | 84 | 751 | fputc('"', out); | 85 | 18.5k | for (p = data; p && *p; p++) { | 86 | 17.8k | if ((unsigned char) *p == 0x22 || /* " */ | 87 | 17.5k | (unsigned char) *p == 0x5c || /* \ */ | 88 | 8.91k | (unsigned char) *p == 0x60 || /* ` */ | 89 | 8.63k | (unsigned char) *p == 0x24 || /* $ */ | 90 | 8.44k | !isprint((unsigned char) *p) || | 91 | 17.8k | iscntrl((unsigned char) *p)) { | 92 | | | 93 | 13.3k | fprintf(out, "\\x%02x", (unsigned char) *p); | 94 | 13.3k | } else | 95 | 4.53k | fputc(dir == 1 ? toupper(*p) : | 96 | 4.53k | dir == -1 ? tolower(*p) : | 97 | 4.53k | *p, out); | 98 | 17.8k | } | 99 | 751 | fputc('"', out); | 100 | 751 | } |
|
101 | | |
102 | 751 | #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 */ |