add split-insns.sh
authorJacob Lifshay <programmerjake@gmail.com>
Tue, 1 Aug 2023 04:35:13 +0000 (21:35 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Tue, 1 Aug 2023 05:02:12 +0000 (22:02 -0700)
.gitignore
split-insns.sh [new file with mode: 0755]

index 6ce67a3b9457705824b887ab1376bcc73f165a19..2b65439b95f727e19192583e159bbecede4e36d5 100644 (file)
@@ -13,3 +13,6 @@ dist
 /crtl*
 /formal_test_temp
 /test-out/
+*~
+*.~[0-9]~
+*.~[0-9][0-9]~
diff --git a/split-insns.sh b/split-insns.sh
new file mode 100755 (executable)
index 0000000..1ef222a
--- /dev/null
@@ -0,0 +1,140 @@
+#!/bin/bash
+cd "$(dirname "$0")"
+set -C
+
+function note() {
+    echo "$fname:$((lidx + 1)): note: $@"
+}
+
+function warn() {
+    echo "$fname:$((lidx + 1)): warning: $@" >&2
+}
+
+function fatal() {
+    echo "$fname:$((lidx + 1)): fatal: $@" >&2
+    exit 1
+}
+
+function next_line() {
+    line="${lines[++lidx]}"
+}
+
+function skip_comments() {
+    while [[ "$line" =~ ^"<!--" ]]; do
+        next_line
+    done
+}
+
+function hit_eof() {
+    ((lidx >= ${#lines[@]}))
+}
+
+function skip_comments_and_blanks() {
+    while [[ "$line" =~ ^"<!--" || "$line" =~ ^[\ \t]*$ ]]; do
+        if hit_eof; then
+            break
+        fi
+        next_line
+    done
+}
+
+function parse_file() {
+    mapfile -t lines < "$fname"
+    local split_ranges=() start_lidx end_lidx insn_fname
+    lidx=-1
+    next_line
+    until hit_eof; do
+        skip_comments_and_blanks
+        if hit_eof; then
+            break
+        fi
+        [[ "$line" =~ ^"#" ]] || fatal 'missing `#` header line'
+        next_line
+        skip_comments_and_blanks
+        [[ "$line" =~ "-Form"[\ \t]*$ ]] || fatal 'missing `Form` line'
+        next_line
+        skip_comments_and_blanks
+        insn_fname=""
+        while :; do
+            [[ "$line" =~ ^"* "([a-zA-Z0-9.]+)(" "|$) ]] || \
+                fatal 'missing/invalid instruction syntax line'
+            if [[ "$insn_fname" == "" ]]; then
+                insn_fname="${fname%.mdwn}/${BASH_REMATCH[1]}.mdwn"
+            fi
+            next_line
+            if [[ "$line" == "" ]]; then
+                break
+            fi
+        done
+        skip_comments_and_blanks
+        [[ "$line" =~ ^"Pseudo-code:"[\ \t]*$ ]] || fatal 'missing `Form` line'
+        next_line
+        [[ "$line" == "" ]] || fatal 'missing blank line after `Pseudo-code:`'
+        next_line
+        while [[ "$line" =~ ^"<!--" ]]; do
+            next_line
+        done
+        start_lidx="$lidx"
+        while [[ "$line" =~ ^"<!--"|^"    " ]]; do
+            next_line
+        done
+        end_lidx="$lidx"
+        if [[ "$line" =~ ^"[[!inline" ]]; then
+            ((start_lidx == end_lidx)) || \
+                warn "[[!inline]] directive can't be used with other content"
+            note "skipping existing [[!inline]] directive"
+        else
+            [[ "$line" == "" ]] || fatal 'missing blank line after content'
+            split_ranges+=("$start_lidx:$end_lidx $insn_fname")
+        fi
+        until hit_eof || [[ "$line" =~ ^"#" ]]; do
+            next_line
+        done
+    done
+    if ((${#split_ranges[@]} == 0)); then
+        return
+    fi
+    local split_range output_lines=()
+    lidx=-1
+    next_line
+    for split_range in "${split_ranges[@]}"; do
+        [[ "$split_range" =~ ^([0-9]+)':'([0-9]+)' '(.*)$ ]] || \
+            fatal "failed to parse split_range=$split_range"
+        start_lidx="${BASH_REMATCH[1]}"
+        end_lidx="${BASH_REMATCH[2]}"
+        insn_fname="${BASH_REMATCH[3]}"
+        while ((lidx < start_lidx)); do
+            output_lines+=("$line")
+            next_line
+        done
+        mkdir -p "$(dirname "$insn_fname")"
+        while ((lidx < end_lidx)); do
+            echo "$line"
+            next_line
+        done > "$insn_fname" || fatal "failed to write to $insn_fname"
+        output_lines+=(\
+            "[[!inline pagenames=\"${insn_fname%.mdwn}\" raw=\"yes\"]]")
+    done
+    until hit_eof; do
+        output_lines+=("$line")
+        next_line
+    done
+    printf "%s\n" "${output_lines[@]}" > "$fname.tmp" || \
+        fatal "failed to write to $fname.tmp"
+    mv -v --backup=t "$fname.tmp" "$fname" || fatal "mv failed"
+}
+
+function main() {
+    for fname in openpower/isa/*.mdwn; do
+        parse_file
+    done
+}
+
+if [[ "$*" != "" ]]; then
+    cat <<EOF >&2
+usage: $0
+take all instructions' pseudo-code and move it to a separate file for each
+EOF
+    exit 1
+fi
+main
\ No newline at end of file