Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) #include "string2.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) const char *graph_dotted_line =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 	"---------------------------------------------------------------------"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 	"---------------------------------------------------------------------"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 	"---------------------------------------------------------------------";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) const char *dots =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 	"....................................................................."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 	"....................................................................."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 	".....................................................................";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #define K 1024LL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * perf_atoll()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * Parse (\d+)(b|B|kb|KB|mb|MB|gb|GB|tb|TB) (e.g. "256MB")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * and return its numeric value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) s64 perf_atoll(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	s64 length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	if (!isdigit(str[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 		goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	length = strtoll(str, &p, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	switch (c = *p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		case 'b': case 'B':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 			if (*p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 				goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 			__fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		case '\0':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 			return length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 			goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		/* two-letter suffices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		case 'k': case 'K':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 			length <<= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		case 'm': case 'M':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 			length <<= 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		case 'g': case 'G':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 			length <<= 30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		case 't': case 'T':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 			length <<= 40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	/* we want the cases to match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	if (islower(c)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		if (strcmp(p, "b") != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 			goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		if (strcmp(p, "B") != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 			goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	return length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) /* Character class matching */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) static bool __match_charclass(const char *pat, char c, const char **npat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	bool complement = false, ret = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	if (*pat == '!') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		complement = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		pat++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	if (*pat++ == c)	/* First character is special */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	while (*pat && *pat != ']') {	/* Matching */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		if (*pat == '-' && *(pat + 1) != ']') {	/* Range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 			if (*(pat - 1) <= c && c <= *(pat + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 				goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 			if (*(pat - 1) > *(pat + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 				goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 			pat += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		} else if (*pat++ == c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 			goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	if (!*pat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	ret = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	while (*pat && *pat != ']')	/* Searching closing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		pat++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	if (!*pat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	*npat = pat + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	return complement ? !ret : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* Glob/lazy pattern matching */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static bool __match_glob(const char *str, const char *pat, bool ignore_space,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 			bool case_ins)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	while (*str && *pat && *pat != '*') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		if (ignore_space) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 			/* Ignore spaces for lazy matching */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 			if (isspace(*str)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 				str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 			if (isspace(*pat)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 				pat++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		if (*pat == '?') {	/* Matches any single character */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 			str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 			pat++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		} else if (*pat == '[')	/* Character classes/Ranges */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 			if (__match_charclass(pat + 1, *str, &pat)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 				str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 			} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 				return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		else if (*pat == '\\') /* Escaped char match as normal char */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 			pat++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		if (case_ins) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 			if (tolower(*str) != tolower(*pat))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 				return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		} else if (*str != *pat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		pat++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	/* Check wild card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	if (*pat == '*') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		while (*pat == '*')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 			pat++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		if (!*pat)	/* Tail wild card matches all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 			return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		while (*str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 			if (__match_glob(str++, pat, ignore_space, case_ins))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 				return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	return !*str && !*pat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)  * strglobmatch - glob expression pattern matching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)  * @str: the target string to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)  * @pat: the pattern string to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)  * This returns true if the @str matches @pat. @pat can includes wildcards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)  * ('*','?') and character classes ([CHARS], complementation and ranges are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)  * also supported). Also, this supports escape character ('\') to use special
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)  * characters as normal character.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)  * Note: if @pat syntax is broken, this always returns false.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) bool strglobmatch(const char *str, const char *pat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	return __match_glob(str, pat, false, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) bool strglobmatch_nocase(const char *str, const char *pat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	return __match_glob(str, pat, false, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)  * strlazymatch - matching pattern strings lazily with glob pattern
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)  * @str: the target string to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  * @pat: the pattern string to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)  * This is similar to strglobmatch, except this ignores spaces in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)  * the target string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) bool strlazymatch(const char *str, const char *pat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	return __match_glob(str, pat, true, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)  * strtailcmp - Compare the tail of two strings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)  * @s1: 1st string to be compared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)  * @s2: 2nd string to be compared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)  * Return 0 if whole of either string is same as another's tail part.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int strtailcmp(const char *s1, const char *s2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	int i1 = strlen(s1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	int i2 = strlen(s2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	while (--i1 >= 0 && --i2 >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		if (s1[i1] != s2[i2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 			return s1[i1] - s2[i2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	 * FIXME: replace this with an expression using log10() when we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	 * find a suitable implementation, maybe the one in the dvb drivers...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	 * "%s == %d || " = log10(MAXINT) * 2 + 8 chars for the operators
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	size_t size = nints * 28 + 1; /* \0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	size_t i, printed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	char *expr = malloc(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	if (expr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		const char *or_and = "||", *eq_neq = "==";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		char *e = expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		if (!in) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 			or_and = "&&";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 			eq_neq = "!=";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		for (i = 0; i < nints; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 			if (printed == size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 				goto out_err_overflow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 			if (i > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 				printed += scnprintf(e + printed, size - printed, " %s ", or_and);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 			printed += scnprintf(e + printed, size - printed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 					     "%s %s %d", var, eq_neq, ints[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	return expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) out_err_overflow:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	free(expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /* Like strpbrk(), but not break if it is right after a backslash (escaped) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) char *strpbrk_esc(char *str, const char *stopset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	char *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		ptr = strpbrk(str, stopset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		if (ptr == str ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		    (ptr == str + 1 && *(ptr - 1) != '\\'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		str = ptr + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	} while (ptr && *(ptr - 1) == '\\' && *(ptr - 2) != '\\');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	return ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /* Like strdup, but do not copy a single backslash */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) char *strdup_esc(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	char *s, *d, *p, *ret = strdup(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	d = strchr(ret, '\\');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	if (!d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	s = d + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		if (*s == '\0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 			*d = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		p = strchr(s + 1, '\\');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		if (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 			memmove(d, s, p - s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 			d += p - s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 			s = p + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 			memmove(d, s, strlen(s) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	} while (p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }