mirror of
https://codeberg.org/libreboot/lbmk.git
synced 2026-07-13 14:59:34 +02:00
config/git: import suckless sbase
i currently use the output of sha512sum in several places of xbmk, which is a bit unreliable in case output changes. other cases where i use util outputs in variables are probably reliable, because i'm using mostly posix utilities in those. to mitigate this, i now import suckless sbase, which has a reasonable sha512sum implementation. *every* binary it builds is being placed in build.list, because i'll probably start using more of them. for example, i may start modifying the "date" implementation, adding the GNU-specific options that i need as mentioned on init.sh i'm importing it in util/ because the sha512sum util is needed for verifying project sources, so if sbase itself is a "project source", that means we can into a chicken and egg bootstrapping problem. this is sbase at revision: 055cc1ae1b3a13c3d8f25af0a4a3316590efcd48 Signed-off-by: Leah Rowe <leah@libreboot.org>
This commit is contained in:
+300
@@ -0,0 +1,300 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "utf.h"
|
||||
#include "util.h"
|
||||
|
||||
static int cflag = 0;
|
||||
static int dflag = 0;
|
||||
static int sflag = 0;
|
||||
|
||||
struct range {
|
||||
Rune start;
|
||||
Rune end;
|
||||
size_t quant;
|
||||
};
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
int (*check)(Rune);
|
||||
} classes[] = {
|
||||
{ "alnum", isalnumrune },
|
||||
{ "alpha", isalpharune },
|
||||
{ "blank", isblankrune },
|
||||
{ "cntrl", iscntrlrune },
|
||||
{ "digit", isdigitrune },
|
||||
{ "graph", isgraphrune },
|
||||
{ "lower", islowerrune },
|
||||
{ "print", isprintrune },
|
||||
{ "punct", ispunctrune },
|
||||
{ "space", isspacerune },
|
||||
{ "upper", isupperrune },
|
||||
{ "xdigit", isxdigitrune },
|
||||
};
|
||||
|
||||
static struct range *set1 = NULL;
|
||||
static size_t set1ranges = 0;
|
||||
static int (*set1check)(Rune) = NULL;
|
||||
static struct range *set2 = NULL;
|
||||
static size_t set2ranges = 0;
|
||||
static int (*set2check)(Rune) = NULL;
|
||||
|
||||
static size_t
|
||||
rangelen(struct range r)
|
||||
{
|
||||
return (r.end - r.start + 1) * r.quant;
|
||||
}
|
||||
|
||||
static size_t
|
||||
setlen(struct range *set, size_t setranges)
|
||||
{
|
||||
size_t len = 0, i;
|
||||
|
||||
for (i = 0; i < setranges; i++)
|
||||
len += rangelen(set[i]);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
rstrmatch(Rune *r, char *s, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
if (r[i] != s[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t
|
||||
makeset(char *str, struct range **set, int (**check)(Rune))
|
||||
{
|
||||
Rune *rstr;
|
||||
size_t len, i, j, m, n;
|
||||
size_t q, setranges = 0;
|
||||
int factor, base;
|
||||
|
||||
/* rstr defines at most len ranges */
|
||||
unescape(str);
|
||||
rstr = ereallocarray(NULL, utflen(str) + 1, sizeof(*rstr));
|
||||
len = utftorunestr(str, rstr);
|
||||
*set = ereallocarray(NULL, len, sizeof(**set));
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (rstr[i] == '[') {
|
||||
j = i;
|
||||
nextbrack:
|
||||
if (j >= len)
|
||||
goto literal;
|
||||
for (m = j; m < len; m++)
|
||||
if (rstr[m] == ']') {
|
||||
j = m;
|
||||
break;
|
||||
}
|
||||
if (j == i)
|
||||
goto literal;
|
||||
|
||||
/* CLASSES [=EQUIV=] (skip) */
|
||||
if (j - i > 3 && rstr[i + 1] == '=' && rstr[m - 1] == '=') {
|
||||
if (j - i != 4)
|
||||
goto literal;
|
||||
(*set)[setranges].start = rstr[i + 2];
|
||||
(*set)[setranges].end = rstr[i + 2];
|
||||
(*set)[setranges].quant = 1;
|
||||
setranges++;
|
||||
i = j;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* CLASSES [:CLASS:] */
|
||||
if (j - i > 3 && rstr[i + 1] == ':' && rstr[m - 1] == ':') {
|
||||
for (n = 0; n < LEN(classes); n++) {
|
||||
if (rstrmatch(rstr + i + 2, classes[n].name, j - i - 3)) {
|
||||
*check = classes[n].check;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
eprintf("Invalid character class.\n");
|
||||
}
|
||||
|
||||
/* REPEAT [_*n] (only allowed in set2) */
|
||||
if (j - i > 2 && rstr[i + 2] == '*') {
|
||||
/* check if right side of '*' is a number */
|
||||
q = 0;
|
||||
factor = 1;
|
||||
base = (rstr[i + 3] == '0') ? 8 : 10;
|
||||
for (n = j - 1; n > i + 2; n--) {
|
||||
if (rstr[n] < '0' || rstr[n] > '9') {
|
||||
n = 0;
|
||||
break;
|
||||
}
|
||||
q += (rstr[n] - '0') * factor;
|
||||
factor *= base;
|
||||
}
|
||||
if (n == 0) {
|
||||
j = m + 1;
|
||||
goto nextbrack;
|
||||
}
|
||||
(*set)[setranges].start = rstr[i + 1];
|
||||
(*set)[setranges].end = rstr[i + 1];
|
||||
(*set)[setranges].quant = q ? q : setlen(set1, MAX(set1ranges, 1));
|
||||
setranges++;
|
||||
i = j;
|
||||
continue;
|
||||
}
|
||||
|
||||
j = m + 1;
|
||||
goto nextbrack;
|
||||
}
|
||||
literal:
|
||||
/* RANGES [_-__-_], _-__-_ */
|
||||
/* LITERALS _______ */
|
||||
(*set)[setranges].start = rstr[i];
|
||||
|
||||
if (i < len - 2 && rstr[i + 1] == '-' && rstr[i + 2] >= rstr[i])
|
||||
i += 2;
|
||||
(*set)[setranges].end = rstr[i];
|
||||
(*set)[setranges].quant = 1;
|
||||
setranges++;
|
||||
}
|
||||
|
||||
free(rstr);
|
||||
return setranges;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
eprintf("usage: %s [-cCds] set1 [set2]\n", argv0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
Rune r, lastrune = 0;
|
||||
size_t off1, off2, i, m;
|
||||
int ret = 0;
|
||||
|
||||
ARGBEGIN {
|
||||
case 'c':
|
||||
case 'C':
|
||||
cflag = 1;
|
||||
break;
|
||||
case 'd':
|
||||
dflag = 1;
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
} ARGEND
|
||||
|
||||
if (!argc || argc > 2 || (argc == 1 && dflag == sflag))
|
||||
usage();
|
||||
set1ranges = makeset(argv[0], &set1, &set1check);
|
||||
if (argc == 2)
|
||||
set2ranges = makeset(argv[1], &set2, &set2check);
|
||||
|
||||
if (!dflag || (argc == 2 && sflag)) {
|
||||
/* sanity checks as we are translating */
|
||||
if (!sflag && !set2ranges && !set2check)
|
||||
eprintf("cannot map to an empty set.\n");
|
||||
if (set2check && set2check != islowerrune &&
|
||||
set2check != isupperrune) {
|
||||
eprintf("can only map to 'lower' and 'upper' class.\n");
|
||||
}
|
||||
}
|
||||
read:
|
||||
if (!efgetrune(&r, stdin, "<stdin>")) {
|
||||
ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>");
|
||||
return ret;
|
||||
}
|
||||
if (argc == 1 && sflag)
|
||||
goto write;
|
||||
for (i = 0, off1 = 0; i < set1ranges; off1 += rangelen(set1[i]), i++) {
|
||||
if (set1[i].start <= r && r <= set1[i].end) {
|
||||
if (dflag) {
|
||||
if (cflag)
|
||||
goto write;
|
||||
else
|
||||
goto read;
|
||||
}
|
||||
if (cflag)
|
||||
goto write;
|
||||
|
||||
/* map r to set2 */
|
||||
if (set2check) {
|
||||
if (set2check == islowerrune)
|
||||
r = tolowerrune(r);
|
||||
else
|
||||
r = toupperrune(r);
|
||||
} else {
|
||||
off1 += r - set1[i].start;
|
||||
if (off1 > setlen(set2, set2ranges) - 1) {
|
||||
r = set2[set2ranges - 1].end;
|
||||
goto write;
|
||||
}
|
||||
for (m = 0, off2 = 0; m < set2ranges; m++) {
|
||||
if (off2 + rangelen(set2[m]) > off1) {
|
||||
m++;
|
||||
break;
|
||||
}
|
||||
off2 += rangelen(set2[m]);
|
||||
}
|
||||
m--;
|
||||
r = set2[m].start + (off1 - off2) / set2[m].quant;
|
||||
}
|
||||
goto write;
|
||||
}
|
||||
}
|
||||
if (set1check && set1check(r)) {
|
||||
if (cflag)
|
||||
goto write;
|
||||
if (dflag)
|
||||
goto read;
|
||||
if (set2check) {
|
||||
if (set2check == islowerrune)
|
||||
r = tolowerrune(r);
|
||||
else
|
||||
r = toupperrune(r);
|
||||
} else {
|
||||
r = set2[set2ranges - 1].end;
|
||||
}
|
||||
goto write;
|
||||
}
|
||||
if (!dflag && cflag) {
|
||||
if (set2check) {
|
||||
if (set2check == islowerrune)
|
||||
r = tolowerrune(r);
|
||||
else
|
||||
r = toupperrune(r);
|
||||
} else {
|
||||
r = set2[set2ranges - 1].end;
|
||||
}
|
||||
goto write;
|
||||
}
|
||||
if (dflag && cflag)
|
||||
goto read;
|
||||
write:
|
||||
if (argc == 1 && sflag && r == lastrune) {
|
||||
if (set1check && set1check(r))
|
||||
goto read;
|
||||
for (i = 0; i < set1ranges; i++) {
|
||||
if (set1[i].start <= r && r <= set1[i].end)
|
||||
goto read;
|
||||
}
|
||||
}
|
||||
if (argc == 2 && sflag && r == lastrune) {
|
||||
if (set2check && set2check(r))
|
||||
goto read;
|
||||
for (i = 0; i < set2ranges; i++) {
|
||||
if (set2[i].start <= r && r <= set2[i].end)
|
||||
goto read;
|
||||
}
|
||||
}
|
||||
efputrune(&r, stdout, "<stdout>");
|
||||
lastrune = r;
|
||||
goto read;
|
||||
}
|
||||
Reference in New Issue
Block a user