gen-verstrs.pl revision fb96f4dd
1#!/usr/bin/env perl 2# 3# Generate C file that contains version strings 4 5($header # This is lsquic.h that contains version enum which we parse 6 , $outfile # This is destination C file 7 ) = @ARGV; 8 9open HEADER, $header 10 or die "cannot open $header for reading: $!"; 11open OUT, ">$outfile" 12 or die "cannot open $outfile for writing: $!"; 13 14while (<HEADER>) { 15 if (/^enum lsquic_version$/ .. /^}/) { 16 if (/^\s*(LSQVER_0*(\d+)),\s*$/ && $1 ne 'LSQVER_098') { 17 if ($2 < 50) { 18 push @enums, $1; 19 push @versions, $2; 20 } 21 push @all_versions, $1; 22 push @all_alpns, "h3-Q0$2"; 23 } 24 if (/^\s*(LSQVER_ID(\d+))\b/) { 25 push @draft_versions, $2; 26 push @all_versions, $1; 27 push @all_alpns, "h3-$2"; 28 } 29 } 30} 31 32close HEADER; 33 34$timestamp = localtime; 35 36print OUT <<C_CODE; 37/* 38 * Auto-generated by $0 on $timestamp 39 */ 40 41#include <assert.h> 42#include <string.h> 43 44#include "lsquic.h" 45 46struct lsquic_engine; 47 48static const char *const versions_to_string[ 1 << N_LSQVER ] = { 49C_CODE 50 51$max_mask = (1 << @versions) - 1; 52 53for ($mask = 0; $mask <= $max_mask; ++$mask) { 54 my @indexes; 55 for ($i = 0; $i < @versions; ++$i) { 56 if ($mask & (1 << $i)) { 57 push @indexes, $i; 58 } 59 } 60 print OUT " [", 61 join('|', map "(1<<$_)", @enums[@indexes]) || 0, 62 "] = \"", 63 join(',', @versions[@indexes]), 64 "\",\n"; 65} 66 67$enums = join '|', map "(1<<$_)", sort @enums; 68 69print OUT <<"C_CODE"; 70}; 71 72 73const char * 74lsquic_get_alt_svc_versions (unsigned versions) 75{ 76 /* Limit to versions in versions_to_string: */ 77 versions &= ($enums); 78 return versions_to_string[ versions ]; 79} 80 81C_CODE 82 83 84$all_version_count_and_null = scalar(@all_versions) + 1; 85 86print OUT <<"C_CODE"; 87static const struct { 88 unsigned versions; 89 const char *h3_alpns[$all_version_count_and_null]; 90} vers_2_h3_alnps[] = { 91 { 0, { NULL }}, 92C_CODE 93 94for ($i = 0; $i < (1 << @all_versions); ++$i) 95{ 96 my (@vers, @alpns); 97 for ($j = 0; $j < @all_versions; ++$j) 98 { 99 if ($i & (1 << $j)) 100 { 101 push @vers, $all_versions[$j]; 102 push @alpns, $all_alpns[$j]; 103 } 104 } 105 if (@vers) { 106 print OUT " {", join("|", map "(1<<$_)", @vers), ", ", 107 "{ ", join(", ", (map qq("$_"), @alpns), "NULL"), " }},\n"; 108 } 109} 110 111$all_versions = join "|", map "(1<<$_)", @all_versions; 112 113print OUT <<"C_CODE"; 114}; 115 116const char *const * 117lsquic_get_h3_alpns (unsigned versions) 118{ 119 unsigned i; 120 121 versions &= ($all_versions); 122 123 for (i = 0; i < sizeof(vers_2_h3_alnps) / sizeof(vers_2_h3_alnps[0]); ++i) 124 if (versions == vers_2_h3_alnps[i].versions) 125 return vers_2_h3_alnps[i].h3_alpns; 126 127 assert(0); 128 return vers_2_h3_alnps[0].h3_alpns; 129} 130C_CODE 131 132 133print OUT <<'C_CODE'; 134 135enum lsquic_version 136lsquic_alpn2ver (const char *alpn, size_t len) 137{ 138 static const struct el { 139 size_t len; 140 char alpn[10]; 141 enum lsquic_version version; 142 } map[] = { 143C_CODE 144 145for ($i = 0; $i < @versions; ++$i) { 146 print OUT " {sizeof(\"h3-Q0$versions[$i]\")-1,\"h3-Q0$versions[$i]\", $enums[$i]},\n"; 147} 148 149for ($i = 0; $i < @draft_versions; ++$i) { 150 print OUT " {sizeof(\"h3-$draft_versions[$i]\")-1,\"h3-$draft_versions[$i]\", LSQVER_ID$draft_versions[$i]},\n"; 151} 152 153print OUT <<'C_CODE'; 154 }; 155 const struct el *el; 156 157 if (alpn) 158 for (el = map; el < map + sizeof(map) / sizeof(map[0]); ++el) 159 if (el->len == len && 0 == strncmp(el->alpn, alpn, len)) 160 return el->version; 161 162 return -1; 163} 164C_CODE 165 166close OUT; 167