0001
0002 #include "string2.h"
0003 #include <linux/kernel.h>
0004 #include <linux/string.h>
0005 #include <stdlib.h>
0006
0007 #include <linux/ctype.h>
0008
0009 const char *graph_dotted_line =
0010 "---------------------------------------------------------------------"
0011 "---------------------------------------------------------------------"
0012 "---------------------------------------------------------------------";
0013 const char *dots =
0014 "....................................................................."
0015 "....................................................................."
0016 ".....................................................................";
0017
0018 #define K 1024LL
0019
0020
0021
0022
0023
0024 s64 perf_atoll(const char *str)
0025 {
0026 s64 length;
0027 char *p;
0028 char c;
0029
0030 if (!isdigit(str[0]))
0031 goto out_err;
0032
0033 length = strtoll(str, &p, 10);
0034 switch (c = *p++) {
0035 case 'b': case 'B':
0036 if (*p)
0037 goto out_err;
0038
0039 __fallthrough;
0040 case '\0':
0041 return length;
0042 default:
0043 goto out_err;
0044
0045 case 'k': case 'K':
0046 length <<= 10;
0047 break;
0048 case 'm': case 'M':
0049 length <<= 20;
0050 break;
0051 case 'g': case 'G':
0052 length <<= 30;
0053 break;
0054 case 't': case 'T':
0055 length <<= 40;
0056 break;
0057 }
0058
0059 if (islower(c)) {
0060 if (strcmp(p, "b") != 0)
0061 goto out_err;
0062 } else {
0063 if (strcmp(p, "B") != 0)
0064 goto out_err;
0065 }
0066 return length;
0067
0068 out_err:
0069 return -1;
0070 }
0071
0072
0073 static bool __match_charclass(const char *pat, char c, const char **npat)
0074 {
0075 bool complement = false, ret = true;
0076
0077 if (*pat == '!') {
0078 complement = true;
0079 pat++;
0080 }
0081 if (*pat++ == c)
0082 goto end;
0083
0084 while (*pat && *pat != ']') {
0085 if (*pat == '-' && *(pat + 1) != ']') {
0086 if (*(pat - 1) <= c && c <= *(pat + 1))
0087 goto end;
0088 if (*(pat - 1) > *(pat + 1))
0089 goto error;
0090 pat += 2;
0091 } else if (*pat++ == c)
0092 goto end;
0093 }
0094 if (!*pat)
0095 goto error;
0096 ret = false;
0097
0098 end:
0099 while (*pat && *pat != ']')
0100 pat++;
0101 if (!*pat)
0102 goto error;
0103 *npat = pat + 1;
0104 return complement ? !ret : ret;
0105
0106 error:
0107 return false;
0108 }
0109
0110
0111 static bool __match_glob(const char *str, const char *pat, bool ignore_space,
0112 bool case_ins)
0113 {
0114 while (*str && *pat && *pat != '*') {
0115 if (ignore_space) {
0116
0117 if (isspace(*str)) {
0118 str++;
0119 continue;
0120 }
0121 if (isspace(*pat)) {
0122 pat++;
0123 continue;
0124 }
0125 }
0126 if (*pat == '?') {
0127 str++;
0128 pat++;
0129 continue;
0130 } else if (*pat == '[')
0131 if (__match_charclass(pat + 1, *str, &pat)) {
0132 str++;
0133 continue;
0134 } else
0135 return false;
0136 else if (*pat == '\\')
0137 pat++;
0138 if (case_ins) {
0139 if (tolower(*str) != tolower(*pat))
0140 return false;
0141 } else if (*str != *pat)
0142 return false;
0143 str++;
0144 pat++;
0145 }
0146
0147 if (*pat == '*') {
0148 while (*pat == '*')
0149 pat++;
0150 if (!*pat)
0151 return true;
0152 while (*str)
0153 if (__match_glob(str++, pat, ignore_space, case_ins))
0154 return true;
0155 }
0156 return !*str && !*pat;
0157 }
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171 bool strglobmatch(const char *str, const char *pat)
0172 {
0173 return __match_glob(str, pat, false, false);
0174 }
0175
0176 bool strglobmatch_nocase(const char *str, const char *pat)
0177 {
0178 return __match_glob(str, pat, false, true);
0179 }
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189 bool strlazymatch(const char *str, const char *pat)
0190 {
0191 return __match_glob(str, pat, true, false);
0192 }
0193
0194
0195
0196
0197
0198
0199
0200
0201 int strtailcmp(const char *s1, const char *s2)
0202 {
0203 int i1 = strlen(s1);
0204 int i2 = strlen(s2);
0205 while (--i1 >= 0 && --i2 >= 0) {
0206 if (s1[i1] != s2[i2])
0207 return s1[i1] - s2[i2];
0208 }
0209 return 0;
0210 }
0211
0212 char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints)
0213 {
0214
0215
0216
0217
0218
0219
0220 size_t size = nints * 28 + 1;
0221 size_t i, printed = 0;
0222 char *expr = malloc(size);
0223
0224 if (expr) {
0225 const char *or_and = "||", *eq_neq = "==";
0226 char *e = expr;
0227
0228 if (!in) {
0229 or_and = "&&";
0230 eq_neq = "!=";
0231 }
0232
0233 for (i = 0; i < nints; ++i) {
0234 if (printed == size)
0235 goto out_err_overflow;
0236
0237 if (i > 0)
0238 printed += scnprintf(e + printed, size - printed, " %s ", or_and);
0239 printed += scnprintf(e + printed, size - printed,
0240 "%s %s %d", var, eq_neq, ints[i]);
0241 }
0242 }
0243
0244 return expr;
0245
0246 out_err_overflow:
0247 free(expr);
0248 return NULL;
0249 }
0250
0251
0252 char *strpbrk_esc(char *str, const char *stopset)
0253 {
0254 char *ptr;
0255
0256 do {
0257 ptr = strpbrk(str, stopset);
0258 if (ptr == str ||
0259 (ptr == str + 1 && *(ptr - 1) != '\\'))
0260 break;
0261 str = ptr + 1;
0262 } while (ptr && *(ptr - 1) == '\\' && *(ptr - 2) != '\\');
0263
0264 return ptr;
0265 }
0266
0267
0268 char *strdup_esc(const char *str)
0269 {
0270 char *s, *d, *p, *ret = strdup(str);
0271
0272 if (!ret)
0273 return NULL;
0274
0275 d = strchr(ret, '\\');
0276 if (!d)
0277 return ret;
0278
0279 s = d + 1;
0280 do {
0281 if (*s == '\0') {
0282 *d = '\0';
0283 break;
0284 }
0285 p = strchr(s + 1, '\\');
0286 if (p) {
0287 memmove(d, s, p - s);
0288 d += p - s;
0289 s = p + 1;
0290 } else
0291 memmove(d, s, strlen(s) + 1);
0292 } while (p);
0293
0294 return ret;
0295 }
0296
0297 unsigned int hex(char c)
0298 {
0299 if (c >= '0' && c <= '9')
0300 return c - '0';
0301 if (c >= 'a' && c <= 'f')
0302 return c - 'a' + 10;
0303 return c - 'A' + 10;
0304 }