This repository has been archived on 2022-05-21. You can view files and clone it, but cannot push or open issues or pull requests.
LEFTONE/tool/benum.sh

142 lines
2.3 KiB
Bash
Raw Normal View History

#!/bin/bash
set -eu
if [[ -z ${1+x} || -z ${2+x} ]]; then
echo "usage: cat <file> | ./benum.sh <dst path without extension> <header path>"
exit 1
fi
DSTPATH="$1"
DSTDIR=$(dirname "$DSTPATH")
HEADERPATH="$2"
if [[ $DSTPATH =~ /$ ]]; then
echo "destination path must be a filename without extension" >&2
exit 1
fi
if [[ ! -d $DSTDIR ]]; then
echo "no such directory: $DSTDIR" >&2
exit 1
fi
preprocess=$(cat << EOS
s|^\s*||
s|\s*$||
/^\/\* *BENUM *BEGIN.*\*\/$/,/^\/\* *BENUM *END *\*\/$/ ! d
/^\/\* *BENUM *BEGIN.*\*\/$/ {
s|^\/\* *BENUM *BEGIN *([^ ]*) *\*\/$|^\1|
p
s|.||g
x
b
}
/^\/\* *BENUM *END *\*\/$/ {
x
s|\s||g
s|,|\\n|g
s|\\n\\n*|\\n|g
s|^\\n||
s|\\n$||
p; b
}
H
EOS
)
header=$(cat << EOS
#include <stdbool.h>
#include <stddef.h>
EOS
)
src=$(cat << EOS
#include "$HEADERPATH"
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
EOS
)
name=
NAME=
list=()
output_header() {
if [[ -z $name ]]; then return; fi
cat << EOS
#define ${NAME}_EACH(PROC) do { \\
$(for item in ${list[@]}; do
echo "PROC($item, ${item,,}); \\"
done)
} while (0)
#define ${NAME}_COUNT ${#list[@]}
const char* ${name}_stringify(${name}_t v);
bool ${name}_unstringify(${name}_t* v, const char* str, size_t len);
EOS
}
output_source() {
if [[ -z $name ]]; then return; fi
cat << EOS
const char* ${name}_stringify(${name}_t v) {
switch (v) {
$(for item in ${list[@]}; do
echo "case ${NAME}_$item: return \"$item\";"
done)
}
assert(false);
return NULL;
}
bool ${name}_unstringify(${name}_t* v, const char* str, size_t len) {
assert(v != NULL);
assert(str != NULL || len == 0);
$(for item in ${list[@]}; do
echo "if (len == ${#item} && strncmp(str, \"$item\", len) == 0) {"
echo " *v = ${NAME}_$item;"
echo " return true;"
echo "}"
done)
return false;
}
EOS
}
output() {
header+=$(output_header)
src+=$(output_source)
}
while read line; do
if [[ $line =~ ^\^(.*)$ ]]; then
output
name="${BASH_REMATCH[1]}"
name="${name,,}"
NAME="${name^^}"
list=()
else
if [[ ! $line =~ ^${NAME}_(.*)$ ]]; then
echo invalid naming rule: "$line" >&2
exit 1
fi
list+=(${BASH_REMATCH[1]})
fi
done < <(cat | sed -r -n "$preprocess")
output
echo "$header" > "$DSTPATH.h"
echo "$src" > "$DSTPATH.c"