180 lines
5.3 KiB
Awk
180 lines
5.3 KiB
Awk
# Protocol Buffers - Google's data interchange format
|
|
# Copyright 2023 Google Inc. All rights reserved.
|
|
# https://developers.google.com/protocol-buffers/
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are
|
|
# met:
|
|
#
|
|
# * Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# * Redistributions in binary form must reproduce the above
|
|
# copyright notice, this list of conditions and the following disclaimer
|
|
# in the documentation and/or other materials provided with the
|
|
# distribution.
|
|
# * Neither the name of Google Inc. nor the names of its
|
|
# contributors may be used to endorse or promote products derived from
|
|
# this software without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
noop = 0
|
|
|
|
function join(array, len, sep)
|
|
{
|
|
if(len== 0) {
|
|
return ""
|
|
}
|
|
result = array[1]
|
|
for (i = 2; i <= len; i++)
|
|
result = result sep array[i]
|
|
return result
|
|
}
|
|
|
|
function transform_field(field)
|
|
{
|
|
if (!match(field, /\w+\s*=\s*[0-9-]+/)) {
|
|
return field
|
|
}
|
|
if (match(field, /(.*[0-9])\s*\[(.*)\];(.*)/, arr)) {
|
|
field_def = arr[1]
|
|
existing_options = arr[2]
|
|
field_comments = arr[3]
|
|
} else {
|
|
match(field, /(.*);(.*)/, arr)
|
|
field_def = arr[1]
|
|
field_comments = arr[2]
|
|
existing_options = 0
|
|
}
|
|
num_options = 0
|
|
|
|
if(syntax == 2) {
|
|
sub(/\<optional /, "", field_def)
|
|
sub(/\<packed = true\>/, "features.repeated_field_encoding = PACKED", existing_options)
|
|
sub(/\<packed = false\>,/, "", existing_options)
|
|
sub(/,?packed = false\>/, "", existing_options)
|
|
if (match($0, /\<required\>/)) {
|
|
sub(/\<required /, "", field_def)
|
|
options[++num_options] = "features.field_presence = LEGACY_REQUIRED"
|
|
}
|
|
}
|
|
|
|
if(syntax == 3) {
|
|
sub(/\<packed = false\>/, "features.repeated_field_encoding = EXPANDED", existing_options)
|
|
sub(/\<packed = true\>,/, "", existing_options)
|
|
sub(/,?packed = true\>/, "", existing_options)
|
|
if (match($0, /\<optional\>/)) {
|
|
sub(/\<optional /, "", field_def)
|
|
options[++num_options] = "features.field_presence = EXPLICIT"
|
|
}
|
|
}
|
|
|
|
if (existing_options && num_options > 0) {
|
|
ret = field_def " [" existing_options ", " join(options, num_options, ",") "];" field_comments
|
|
} else if (existing_options) {
|
|
ret = field_def " [" existing_options "];" field_comments
|
|
} else if(num_options > 0) {
|
|
ret = field_def " [" join(options, num_options, ",") "];" field_comments
|
|
} else {
|
|
ret = field_def ";" field_comments
|
|
}
|
|
delete options
|
|
return ret
|
|
}
|
|
|
|
# Skip comments
|
|
/^\s*\/\// {
|
|
print $0
|
|
next
|
|
}
|
|
|
|
/syntax = "proto2"/ {
|
|
print "edition = \"2023\";"
|
|
print "import \"third_party/protobuf/cpp_features.proto\";"
|
|
print "option features.enum_type = CLOSED;"
|
|
print "option features.repeated_field_encoding = EXPANDED;"
|
|
print "option features.string_field_validation = NONE;"
|
|
print "option features.json_format = LEGACY_BEST_EFFORT;"
|
|
print "option features.(pb.cpp).legacy_closed_enum = true;"
|
|
syntax = 2
|
|
next
|
|
}
|
|
|
|
/syntax = "proto3"/ {
|
|
print "edition = \"2023\";"
|
|
print "option features.field_presence = IMPLICIT;"
|
|
syntax = 3
|
|
next
|
|
}
|
|
|
|
# Group handling.
|
|
/\<group \w* = [0-9]* {/, /}/ {
|
|
if (match($0, /\<group\>/)) {
|
|
match($0, /(\s*)(\w*)\s*group\s*(\w*)\s*=\s*([0-9]*)\s*{(\s*[^}]*}?)/, arr)
|
|
if (arr[0, "length"] == 0) {
|
|
print("[ERROR] Invalid group match: ", $0)
|
|
exit
|
|
}
|
|
current_group_whitespace = arr[1]
|
|
current_group_presence = arr[2]
|
|
current_group_name = arr[3]
|
|
current_group_number = arr[4]
|
|
current_group_extra = transform_field(arr[5])
|
|
|
|
print current_group_whitespace "message", current_group_name, "{" current_group_extra
|
|
} else if (match($0, /}/)) {
|
|
print $0
|
|
}
|
|
if (match($0, /}/)) {
|
|
$0 = current_group_whitespace current_group_presence " " current_group_name " " tolower(current_group_name) " = " current_group_number " [features.message_encoding = DELIMITED];"
|
|
} else if (match($0, /\<group\>/)) {
|
|
next
|
|
}
|
|
}
|
|
|
|
# Skip declarations we don't transform.
|
|
/^\s*(message|enum|oneof|extend|service)\s+(\w|\.)*\s*{/ {
|
|
noop = 1
|
|
}
|
|
/^\s*rpc\s+\w*\s*\(/ {
|
|
noop = 1
|
|
}
|
|
/^\s*(}|\/\/|$)/ {
|
|
noop = 1
|
|
}
|
|
/^\s*(extensions|package|reserved|import) .*;/ {
|
|
noop = 1
|
|
}
|
|
/^\s*option\s+[a-zA-Z0-9._()]*\s*=.*;/ {
|
|
noop = 1
|
|
}
|
|
/\s*extensions.* \[/, /\]/ {
|
|
noop = 1
|
|
}
|
|
noop {
|
|
print $0
|
|
next
|
|
}
|
|
|
|
/./, /;/ {
|
|
if (buffered_field != "") {
|
|
sub(/\s+/, " ", $0)
|
|
}
|
|
buffered_field = (buffered_field $0)
|
|
if (!match($0, /;/)) {
|
|
next
|
|
}
|
|
print(transform_field(buffered_field))
|
|
buffered_field = ""
|
|
}
|