extract_h2_huffman.sh (3414B)
1 #!/bin/bash 2 # SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) 3 4 set -euo pipefail 5 6 OUT="h2_huffman_insert.h" 7 TMPDIR="$(mktemp -d)" 8 RFC_TEXT_FILE="$TMPDIR/rfc7541.txt" 9 trap 'rm -rf "$TMPDIR"' EXIT 10 11 echo "Downloading RFC specification..." 12 wget --show-progress -O "$RFC_TEXT_FILE" "https://www.rfc-editor.org/rfc/rfc7541.txt" 13 14 echo "Extractibe data..." 15 { 16 gawk -f - "$RFC_TEXT_FILE" <<'END_OF_AWK_SCRIPT' 17 BEGIN { IGNORECASE=1 } 18 { 19 sub(/\r$/, "", $0) # CRLF -> LF (if any) 20 21 # Strictly match table lines 22 if (match($0, 23 /^[ ]+('.'[ ]+)?\([ ]*([0-9]+)[ ]*\)[ ]*\|[ 01|]+[ ]+([0-9A-Fa-f]+)[ ]+\[[ ]*([0-9]{1,2})[ ]*\][ ]*$/, 24 M)) 25 { 26 idx = M[2] + 0 27 hex = M[3] 28 blen = M[4] + 0 29 if (idx <= 255) { 30 code[idx] = strtonum("0x" hex) 31 clen[idx] = blen 32 } 33 } 34 } 35 END { 36 # Check completeness 37 for (i = 0; i <= 255; i++) 38 { 39 if (!(i in code)) { 40 printf("/* ERROR: missing Huffman entry %d */\n", i) > "/dev/stderr" 41 exit 2 42 } 43 } 44 45 print "/**" 46 print " * HTTP/2 static Huffman codes from RFC 7541" 47 print " *" 48 print " * Index is the character value (0..255)." 49 print " * The table values are codes that are left-algined (MSB-aligned) to" 50 print " * the 32 bit value." 51 print " * See https://www.rfc-editor.org/rfc/rfc7541.html#appendix-B" 52 print " *" 53 print " * @note The table does not include EOS code." 54 print " */" 55 print "mhd_constexpr uint_least32_t mhd_h2huff_code_by_sym[256] =" 56 print "{" 57 lens = "" 58 for (i = 0; i <= 255; i++) 59 { 60 blen = clen[i] 61 62 # Check length 63 if (blen < 1 || blen > 32) 64 { 65 printf("/* ERROR: bad bit length %u for index %d */\n", blen, i) > "/dev/stderr" 66 exit 2 67 } 68 69 # Check code value fits into the declared length 70 if (rshift(code[i], blen) != 0) 71 { 72 printf("/* ERROR: code 0x%X for index %d exceeds its length %u */\n", 73 code[i], i, blen) > "/dev/stderr" 74 exit 2 75 } 76 77 # Left-align to the MSB of a 32-bit word 78 shift = 32 - blen 79 msb = lshift(code[i], shift) 80 81 # Check nothing beyond 32 bits (not really needed, the length has been already checked) 82 if (rshift(msb, 32) != 0) 83 { 84 printf("/* ERROR: left-aligned code for index %d does not fit in 32 bits */\n", 85 i) > "/dev/stderr" 86 exit 2 87 } 88 89 # A label for printable US-ASCII chars 90 label = "" 91 if (i >= 32 && i <= 126) 92 { 93 ch = sprintf("%c", i) 94 if (i == 92) ch = "\\" # this prints a single backslash 95 label = sprintf("%c%s%c", 39, ch, 39) 96 } 97 comment = sprintf("/* %3s (%3d) */", label, i) 98 99 printf(" %s 0x%08Xu%s\n", comment, msb, (i < 255 ? "," : "")) 100 lens = (lens sprintf(" %s %2uu%s\n", comment, blen, (i < 255 ? "," : ""))) 101 } 102 print "};" 103 print "" 104 print "" 105 print "/**" 106 print " * HTTP/2 static Huffman codes length in bits from RFC 7541" 107 print " * See https://www.rfc-editor.org/rfc/rfc7541.html#appendix-B" 108 print " *" 109 print " * Index is the character value (0..255)." 110 print " * The table values are lengths of the code in bits." 111 print " * See https://www.rfc-editor.org/rfc/rfc7541.html#appendix-B" 112 print " *" 113 print " * @note The table does not include EOS code." 114 print " */" 115 print "mhd_constexpr uint8_t mhd_h2huff_bitlen_by_sym[256] =" 116 printf ("{\n%s};\n", lens) 117 } 118 END_OF_AWK_SCRIPT 119 } > "$OUT" 120 121 echo "Success." 122 echo "The output file is: $OUT"