Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: CI

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build-and-fuzz:
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- name: Checkout repository
uses: actions/checkout@v7

- name: Install deps
run: sudo apt-get update && sudo apt-get install -y libwayland-dev libxkbcommon-dev

- name: Macro test
run: |
chmod +x fuzz_macros.sh
./fuzz_macros.sh

- name: Build binary
run: |
cc nob.c -o nob
./nob dev

- name: Commit and push sfte.h
if: github.event_name == 'push'
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"

git add sfte.h

if ! git diff --staged --quiet; then
git commit -m "chore: update amalgamation sfte.h [skip ci]"
git push
else
echo "no changes to commit"
fi
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
/vendor/xdg-shell.h
/nob.old
/config.c
/fuzz_macros.log
4 changes: 2 additions & 2 deletions config.def.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
To apply a change, you need to recompile the project using `cc nob.c -o nob && ./nob`.
*/

#define SFTE_COLOR_BG_OPACITY 0xEE
#define SFTE_CURSOR_TRAIL 10
// #define SFTE_COLOR_BG_OPACITY 0xEE
// #define SFTE_CURSOR_TRAIL 10
#define SFTE_FONT_BOLD
#define SFTE_FONT_ITALIC
#define SFTE_FONT_BOLD_ITALIC
Expand Down
110 changes: 110 additions & 0 deletions fuzz_macros.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/bin/bash
# This script is used for CI GitHub action.
#
# It's main point is to confirm that there's no:
# - dead code in macro branches after variable renames,
# - macro-specific code not wrapped in the specific macro.
#
# It works by stripping the section from
# '// >>>CONFIGURATION'
# line to
# '// >>modifiers and shortcuts macros'
# line and grabbing all '_SFTE_ENSURE_RANGE' calls.
# Then, it runs the compilation for every option with their minimum and maximum values.
#
# WARN:
# This might not catch any more complex statements, e.g. when one macro is dependent on another.

set -e

cc nob.c -o nob

# _SFTE_ENSURE_RANGE(macro, min, max) => RANGE|macro|min |max
# _SFTE_ENSURE_DEPS(macro, dep1 && dep2) => DEP |macro|dep1|dep2
EXTRACTED=$(awk '
/\/\/ >>>CONFIGURATION/,/\/\/ >>>PUBLIC API/ {
if ($0 ~ /^_SFTE_ENSURE_RANGE/) {
line = $0
sub(/^[^(]+\(/, "", line) # strip to first (
sub(/\).*$/, "", line) # strip from last ) to end
split(line, p, ",")

for(i=1; i<=3; i++) { # strip from whitespaces
sub(/^[ \t]+/, "", p[i])
sub(/[ \t]+$/, "", p[i])
}

if (p[1] != "" && p[2] != "" && p[3] != "") {
print "RANGE|" p[1] "|" p[2] "|" p[3]
}
}

if ($0 ~ /^_SFTE_ENSURE_DEPS/) {
line = $0
sub(/^[^(]+\(/, "", line) # strip to first (
sub(/\).*$/, "", line) # strip from last ) to end
split(line, p, ",")
macro = p[1] # extract macro
sub(/^[ \t]+/, "", macro)
sub(/[ \t]+$/, "", macro)

sub(/^[^,]+,/, "", line) # strip macro
deps = ""
while (match(line, /SFTE_[A-Z0-9_]+/)) {
deps = deps " " substr(line, RSTART, RLENGTH)
line = substr(line, RSTART + RLENGTH)
}
print "DEP|" macro "|" deps
}
}' sfte_dev.h)

declare -a RANGES
declare -A FORWARD_DEPS # dependencies required to enable a macro
declare -A REVERSE_DEPS # macros that break if a dependency is disabled

while IFS='|' read -r TYPE COL1 COL2 COL3; do
if [[ "$TYPE" == "RANGE" ]]; then
RANGES+=("$COL1|$COL2|$COL3")
elif [[ "$TYPE" == "DEP" ]]; then
MACRO="$COL1"
DEPS="$COL2"
FORWARD_DEPS["$MACRO"]="$DEPS"
for DEP in $DEPS; do
REVERSE_DEPS["$DEP"]+="$MACRO "
done
fi
done <<< "$EXTRACTED"

cp sfte_dev.h sfte_dev.h.bak
cp sfte.h sfte.h.bak
trap 'mv sfte_dev.h.bak sfte_dev.h; mv sfte.h.bak sfte.h; rm -f fuzz_macros.log' EXIT

for ENTRY in "${RANGES[@]}"; do
IFS='|' read -r MACRO MIN MAX <<< "$ENTRY"

for VAL in "$MIN" "$MAX"; do
echo "$MACRO = $VAL"
sed -i -E "s/^(#define[[:space:]]+$MACRO[[:space:]]+).*/\1$VAL/" sfte_dev.h
if [[ "$VAL" == "$MAX" && -n "${FORWARD_DEPS[$MACRO]}" ]]; then
# if turning on, turn on dependencies
for DEP in ${FORWARD_DEPS[$MACRO]}; do
echo "enabling dependency: $DEP = 1"
sed -i -E "s/^(#define[[:space:]]+$DEP[[:space:]]+).*/\11/" sfte_dev.h
done
elif [[ "$VAL" == "$MIN" && -n "${REVERSE_DEPS[$MACRO]}" ]]; then
# if turning off, turn off anything that relies on it
for REV in ${REVERSE_DEPS[$MACRO]}; do
echo "disabling dependency: $REV = 0"
sed -i -E "s/^(#define[[:space:]]+$REV[[:space:]]+).*/\10/" sfte_dev.h
done
fi

if ! ./nob dev &> fuzz_macros.log; then
echo "build failed: $MACRO=$VAL"
cat fuzz_macros.log
exit 1
fi

cp sfte_dev.h.bak sfte_dev.h
done
done
Loading
Loading