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