#! /usr/bin/env perl # # %CopyrightBegin% # # Copyright Ericsson AB 2009-2016. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # %CopyrightEnd% # use strict; # Generate ADT (Abstract Data Type) access and generation functions # for internal records. # # The following defines which ADT function sets that will be generated # and which record fields that will be exponated. # # (FunctionBaseName => [RecordName, FieldName ...], ...) my %Names = ('msg' => ['dns_rec', 'header', 'qdlist', 'anlist', 'nslist', 'arlist'], 'dns_rr' => ['dns_rr', 'domain', 'type', 'class', 'ttl', 'data'], 'dns_rr_opt' => ['dns_rr_opt', 'domain', 'type', 'udp_payload_size', 'ext_rcode', 'version', 'z', 'data'], 'dns_query' => ['dns_query', 'domain', 'type', 'class'], 'header' => ['dns_header', 'id', 'qr', 'opcode', 'aa', 'tc', 'rd', 'ra', 'pr', 'rcode']); # The functions are defined in the __DATA__ section at the end. # Read in __DATA__ and merge lines. my $line = ''; my @DATA; my @INDEX; while() { chomp; $line .= $_; unless ($line =~ s/\\$//) { if ($line =~ s/^[+]//) { push(@INDEX, $line); } else { push(@DATA, $line); } $line = ''; } } $" = ','; $\ = "\n"; foreach my $Name (sort keys %Names) { my $r = $Names{$Name}; # Create substitutions for this Name my ($Record, @Fields) = @{ $r }; my @FieldMatchValues; my @FieldValueTuples; my @Values; my $n = $#{ $r }; for my $i ( 1 .. $n ) { push(@FieldMatchValues, "$Fields[$i-1]=V$i"); push(@FieldValueTuples, "{$Fields[$i-1],V$i}"); push(@Values, "V$i"); } # "@FieldMatchValues" = "field1=V1,field2=V2"...",fieldN=VN" # "@FieldMatchTuples" = "{field1,V1},{field2,V2}"...",{fieldN,VN}" # "@Values" = "V1,V2"...",VN" my @D = @DATA; foreach my $line (@D) { # Ignore !name lines if ($line =~ s/^\!(\S+)\s+//) { next if $1 eq $Name; } my $m = 1; # For leading * iterate $n times, otherwise once $line =~ s/^\s*[*]// and $m = $n; for my $i ( 1 .. $m ) { # For this iteration - substitute and print my $Value = "V$i"; my $SemicolonDot = ";"; $SemicolonDot = "." if $i == $m; my @ValuesIgnoreValue = @Values; $ValuesIgnoreValue[$i-1] = '_'; # "$Value" = "V1" or "V2" or ... "VN" # "@ValuesIgnoreValue" = "_,V2"...",VN" # or "V1,_"...",VN" # or ... "V1,V2"...",_" $_ = $line; s/FieldMatchValues\b/@FieldMatchValues/g; s/FieldValueTuples\b/@FieldValueTuples/g; s/Field\b/$Fields[$i-1]/g; s/Name\b/$Name/g; s/Record\b/$Record/g; s/ValuesIgnoreValue\b/@ValuesIgnoreValue/g; s/Values\b/@Values/g; s/Value\b/$Value/g; s/[;][.]/$SemicolonDot/g; s/->\s*/->\n /; print; } } } for my $i ( 0 .. $#INDEX ) { my $line = $INDEX[$i]; if ($line =~ s/^[*]//) { foreach my $Name (sort keys %Names) { my $r = $Names{$Name}; my ($Record) = @{ $r }; $_ = $line; s/Name\b/$Name/g; s/Record\b/$Record/g; s/->\s*/->\n /; print; } } else { print $line; } } # Trailing \ will merge line with the following. # Leading * will iterate the (merged) line over all field names. # Sub-words in the loop above are substituted. __DATA__ %% %% Abstract Data Type functions for #Record{} %% %% -export([Name/1, Name/2, %% make_Name/0, make_Name/1, make_Name/2, make_Name/3]). %% Split #Record{} into property list %% Name(#Record{FieldMatchValues}) -> \ [FieldValueTuples]. %% Get one field value from #Record{} %% *Name(#Record{Field=Value}, Field) -> \ Value; %% Map field name list to value list from #Record{} %% Name(#Record{}, []) -> \ []; *Name(#Record{Field=Value}=R, [Field|L]) -> \ [Value|Name(R, L)];. %% Generate default #Record{} %% make_Name() -> \ #Record{}. %% Generate #Record{} from property list %% make_Name(L) when is_list(L) -> \ make_Name(#Record{}, L). !dns_rr_opt %% Generate #Record{} with one updated field !dns_rr_opt %% !dns_rr_opt *make_Name(Field, Value) -> \ #Record{Field=Value}; %% %% Update #Record{} from property list %% make_Name(#Record{FieldMatchValues}, L) when is_list(L) -> \ do_make_Name(L, Values). do_make_Name([], Values) -> \ #Record{FieldMatchValues}; *do_make_Name([{Field,Value}|L], ValuesIgnoreValue) -> \ do_make_Name(L, Values);. %% Update one field of #Record{} %% *make_Name(#Record{}=R, Field, Value) -> \ R#Record{Field=Value};. +%% Record type index +%% +*record_adts(#Record{}) -> Name; +record_adts(_) -> undefined.