gen-verstrs.pl revision 1245d2e0
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
41#include "lsquic.h"
42
43struct lsquic_engine;
44
45static const char *const versions_to_string[ 1 << N_LSQVER ] = {
46C_CODE
47
48$max_mask = (1 << @versions) - 1;
49
50for ($mask = 0; $mask <= $max_mask; ++$mask) {
51    my @indexes;
52    for ($i = 0; $i < @versions; ++$i) {
53        if ($mask & (1 << $i)) {
54            push @indexes, $i;
55        }
56    }
57    print OUT "    [",
58        join('|', map "(1<<$_)", @enums[@indexes]) || 0,
59        "] = \"",
60        join(',', @versions[@indexes]),
61        "\",\n";
62}
63
64$enums = join '|', map "(1<<$_)", sort @enums;
65
66print OUT <<"C_CODE";
67};
68
69
70const char *
71lsquic_get_alt_svc_versions (unsigned versions)
72{
73    /* Limit to versions in versions_to_string: */
74    versions &= ($enums);
75    return versions_to_string[ versions ];
76}
77
78C_CODE
79
80
81$all_version_count_and_null = scalar(@all_versions) + 1;
82
83print OUT <<"C_CODE";
84static const struct {
85    unsigned    versions;
86    const char *h3_alpns[$all_version_count_and_null];
87} vers_2_h3_alnps[] = {
88    { 0, { NULL }},
89C_CODE
90
91for ($i = 0; $i < (1 << @all_versions); ++$i)
92{
93    my (@vers, @alpns);
94    for ($j = 0; $j < @all_versions; ++$j)
95    {
96        if ($i & (1 << $j))
97        {
98            push @vers, $all_versions[$j];
99            push @alpns, $all_alpns[$j];
100        }
101    }
102    if (@vers) {
103        print OUT "    {", join("|", map "(1<<$_)", @vers), ", ",
104            "{ ", join(", ", (map qq("$_"), @alpns), "NULL"), " }},\n";
105    }
106}
107
108$all_versions = join "|", map "(1<<$_)", @all_versions;
109
110print OUT <<"C_CODE";
111};
112
113const char *const *
114lsquic_get_h3_alpns (unsigned versions)
115{
116    unsigned i;
117
118    versions &= ($all_versions);
119
120    for (i = 0; i < sizeof(vers_2_h3_alnps) / sizeof(vers_2_h3_alnps[0]); ++i)
121        if (versions == vers_2_h3_alnps[i].versions)
122            return vers_2_h3_alnps[i].h3_alpns;
123
124    assert(0);
125    return vers_2_h3_alnps[0].h3_alpns;
126}
127C_CODE
128
129
130close OUT;
131