1#!/usr/bin/perl -l
2## Copyright (C) 2017 Intel Corporation
3##
4## Permission is hereby granted, free of charge, to any person obtaining a copy
5## of this software and associated documentation files (the "Software"), to deal
6## in the Software without restriction, including without limitation the rights
7## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8## copies of the Software, and to permit persons to whom the Software is
9## furnished to do so, subject to the following conditions:
10##
11## The above copyright notice and this permission notice shall be included in
12## all copies or substantial portions of the Software.
13##
14## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20## THE SOFTWARE.
21##
22use strict;
23my $fname = shift @ARGV
24    or die("Usage: parsetags.pl tags.txt");
25open TAGS, "<", $fname
26    or die("Cannot open $fname: $!");
27
28my %typedescriptions = (
29    "Integer" => "integer",
30    "ByteString" => "byte string",
31    "TextString" => "UTF-8 text string",
32    "Array" => "array",
33    "Map" => "map",
34    "Tag" => "tag",     # shouldn't happen
35    "Simple" => "any simple type",
36    "Boolean" => "boolean",
37    "Null" => "null",
38    "Undefined" => "undefined",
39    "HalfFloat" => "IEEE 754 half-precision floating point",
40    "Float" => "IEEE 754 single-precision floating point",
41    "Double" => "IEEE 754 double-precision floating point"
42);
43
44my %tags;
45while (<TAGS>) {
46    s/\s*#.*$//;
47    next if /^$/;
48    chomp;
49
50    die("Could not parse line \"$_\"")
51        unless /^(\d+);(\w+);([\w,]*);(.*)$/;
52    $tags{$1}{id} = $2;
53    $tags{$1}{semantic} = $4;
54    my @types = split(',', $3);
55    $tags{$1}{types} = \@types;
56}
57close TAGS or die;
58
59my @tagnumbers = sort { $a <=> $b } keys %tags;
60
61print "==== HTML listing ====";
62print "<table>\n  <tr>\n    <th>Tag</th>\n    <th>Data Item</th>\n    <th>Semantics</th>\n  </tr>";
63for my $n (@tagnumbers) {
64    print "  <tr>";
65    print "    <td>$n</td>";
66
67    my @types = @{$tags{$n}{types}};
68    @types = map { $typedescriptions{$_}; } @types;
69    unshift @types, "any"
70        if (scalar @types == 0);
71    printf "    <td>%s</td>\n", join(', ', @types);
72    printf "    <td>%s</td>\n", $tags{$n}{semantic};
73    print "  </td>";
74}
75print "</table>";
76
77print "\n==== enum listing for cbor.h ====\n";
78printf "typedef enum CborKnownTags {";
79my $comma = "";
80for my $n (@tagnumbers) {
81    printf "%s\n    Cbor%sTag%s = %d", $comma,
82        $tags{$n}{id},
83        ' ' x (23 - length($tags{$n}{id})),
84        $n;
85    $comma = ",";
86}
87print "\n} CborKnownTags;";
88print "\n/* #define the constants so we can check with #ifdef */";
89for my $n (@tagnumbers) {
90    printf "#define Cbor%sTag Cbor%sTag\n", $tags{$n}{id}, $tags{$n}{id};
91}
92
93print "\n==== search table ====\n";
94print "struct KnownTagData { uint32_t tag; uint32_t types; };";
95printf "static const struct KnownTagData knownTagData[] = {";
96$comma = "";
97for my $n (@tagnumbers) {
98    my @types = @{$tags{$n}{types}};
99
100    my $typemask;
101    my $shift = 0;
102    for my $type (@types) {
103        die("Too many match types for tag $n") if $shift == 32;
104        my $actualtype = "Cbor${type}Type";
105        $actualtype = "($actualtype+1)" if $type eq "Integer";
106        $typemask .= " | " if $typemask ne "";
107        $typemask .= "((uint8_t)$actualtype << $shift)" if $shift;
108        $typemask .= "(uint8_t)$actualtype" unless $shift;
109        $shift += 8;
110    }
111    $typemask = "0U" if $typemask eq "";
112
113    printf "%s\n    { %d, %s }", $comma, $n, $typemask;
114    $comma = ",";
115}
116print "\n};";
117