%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1996-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%
%%
%%----------------------------------------------------------------------
%% Number of expected shift/reduce warnings
%% This is ugly but...
%%----------------------------------------------------------------------
Expect 2.
%% ----------------------------------------------------------------------
Nonterminals
%% ----------------------------------------------------------------------
accessv1
definition
defvalpart
description
descriptionfield
displaypart
entry
namedbits
fatherobjectname
fieldname
fields
implies
import
import_stuff
imports
imports_from_one_mib
index
indexpartv1
indextypev1
indextypesv1
parentintegers
listofdefinitions
listofimports
mib
mibname
nameassign
newtype
newtypename
objectidentifier
objectname
objecttypev1
prodrel
range_num
referpart
size
sizedescr
statusv1
syntax
tableentrydefinition
traptype
type
usertype
variables
varpart
%v2
moduleidentity
revisionpart
revisions
listofdefinitionsv2
mibid
last_updated
organization
contact_info
revision
revision_string
revision_desc
v1orv2
objectidentity
objecttypev2
unitspart
indexpartv2
indextypesv2
indextypev2
statusv2
accessv2
notification
objectspart
objects
definitionv2
textualconvention
objectgroup
notificationgroup
modulecompliance
mc_modulepart
mc_modules
mc_module
mc_modulenamepart
mc_mandatorypart
mc_compliancepart
mc_compliances
mc_compliance
mc_compliancegroup
mc_object
mc_accesspart
agentcapabilities
ac_status
ac_modulepart
ac_modules
ac_module
ac_modulenamepart
ac_variationpart
ac_variations
ac_variation
ac_accesspart
ac_access
ac_creationpart
syntaxpart
writesyntaxpart
fsyntax
defbitsvalue
defbitsnames
.
%% ----------------------------------------------------------------------
Terminals
%% ----------------------------------------------------------------------
integer variable atom string quote '{' '}' '::=' ':' '=' ',' '.' '(' ')' ';' '|'
'ACCESS'
'BEGIN'
'BIT'
'Counter'
'DEFINITIONS'
'DEFVAL'
'DESCRIPTION'
'DISPLAY-HINT'
'END'
'ENTERPRISE'
'FROM'
'Gauge'
'IDENTIFIER'
'IMPORTS'
'INDEX'
'INTEGER'
'IpAddress'
'NetworkAddress'
'OBJECT'
'OBJECT-TYPE'
'OCTET'
'OF'
'Opaque'
'REFERENCE'
'SEQUENCE'
'SIZE'
'STATUS'
'STRING'
'SYNTAX'
'TRAP-TYPE'
'TimeTicks'
'VARIABLES'
%v2
'LAST-UPDATED'
'ORGANIZATION'
'CONTACT-INFO'
'MODULE-IDENTITY'
'NOTIFICATION-TYPE'
'PRODUCT-RELEASE'
'AGENT-CAPABILITIES'
'INCLUDES'
'SUPPORTS'
'VARIATION'
'CREATION-REQUIRES'
'MODULE-COMPLIANCE'
'OBJECT-GROUP'
'NOTIFICATION-GROUP'
'REVISION'
'OBJECT-IDENTITY'
'MAX-ACCESS'
'UNITS'
'AUGMENTS'
'IMPLIED'
'OBJECTS'
'TEXTUAL-CONVENTION'
'NOTIFICATIONS'
'MODULE'
'MANDATORY-GROUPS'
'GROUP'
'WRITE-SYNTAX'
'MIN-ACCESS'
'BITS'
'DisplayString'
'PhysAddress'
'MacAddress'
'TruthValue'
'TestAndIncr'
'AutonomousType'
'InstancePointer'
'VariablePointer'
'RowPointer'
'RowStatus'
'TimeStamp'
'TimeInterval'
'DateAndTime'
'StorageType'
'TDomain'
'TAddress'
.
Rootsymbol mib.
Endsymbol '$end'.
% **********************************************************************
mib -> mibname 'DEFINITIONS' implies 'BEGIN'
import v1orv2 'END'
: {Version, Defs} = '$6',
#pdata{mib_version = Version,
mib_name = '$1',
imports = '$5',
defs = Defs}.
v1orv2 -> moduleidentity listofdefinitionsv2 :
{v2_mib, ['$1'|lreverse(v1orv2_mod, '$2')]}.
v1orv2 -> listofdefinitions : {v1_mib, lreverse(v1orv2_list, '$1')}.
definition -> objectidentifier : '$1'.
definition -> objecttypev1 : '$1'.
definition -> newtype : '$1'.
definition -> tableentrydefinition : '$1'.
definition -> traptype : '$1'.
listofdefinitions -> definition : ['$1'] .
listofdefinitions -> listofdefinitions definition : ['$2' | '$1'].
import -> '$empty' : [].
import -> 'IMPORTS' imports ';' :
%% i("import ->"
%% "~n imports: ~p", ['$2']),
'$2'.
imports -> imports_from_one_mib :
%% i("imports ->"
%% "~n imports_from_one_mib: ~p", ['$1']),
['$1'].
imports -> imports_from_one_mib imports :
%% i("imports ->"
%% "~n imports_from_one_mib: ~p"
%% "~n imports: ~p", ['$1', '$2']),
['$1' | '$2'].
imports_from_one_mib -> listofimports 'FROM' variable :
%% i("imports_from_one_mib ->"
%% "~n listofimports: ~p"
%% "~n variable: ~p", ['$1', '$3']),
{{val('$3'), lreverse(imports_from_one_mib, '$1')}, line_of('$2')}.
listofimports -> import_stuff :
%% i("listofimports ->"
%% "~n import_stuff: ~p", ['$1']),
['$1'].
listofimports -> listofimports ',' import_stuff :
%% i("listofimports ->"
%% "~n listofimports: ~p"
%% "~n import_stuff: ~p", ['$1', '$3']),
['$3' | '$1'].
import_stuff -> 'OBJECT-TYPE' : {builtin, 'OBJECT-TYPE'}.
import_stuff -> 'TRAP-TYPE' : {builtin, 'TRAP-TYPE'}.
import_stuff -> 'NetworkAddress' : {builtin, 'NetworkAddress'}.
import_stuff -> 'TimeTicks' : {builtin, 'TimeTicks'}.
import_stuff -> 'IpAddress' : {builtin, 'IpAddress'}.
import_stuff -> 'Counter' : {builtin, 'Counter'}.
import_stuff -> 'Gauge' : {builtin, 'Gauge'}.
import_stuff -> 'Opaque' : {builtin, 'Opaque'}.
import_stuff -> variable : filter_v2imports(get(snmp_version), val('$1')).
import_stuff -> atom : {node, val('$1')}.
%%v2
import_stuff -> 'MODULE-IDENTITY'
: ensure_ver(2,'$1'), {builtin, 'MODULE-IDENTITY'}.
import_stuff -> 'NOTIFICATION-TYPE'
: ensure_ver(2,'$1'), {builtin, 'NOTIFICATION-TYPE'}.
import_stuff -> 'AGENT-CAPABILITIES'
: ensure_ver(2,'$1'), {builtin, 'AGENT-CAPABILITIES'}.
import_stuff -> 'MODULE-COMPLIANCE'
: ensure_ver(2,'$1'), {builtin, 'MODULE-COMPLIANCE'}.
import_stuff -> 'NOTIFICATION-GROUP'
: ensure_ver(2,'$1'), {builtin, 'NOTIFICATION-GROUP'}.
import_stuff -> 'OBJECT-GROUP'
: ensure_ver(2,'$1'), {builtin, 'OBJECT-GROUP'}.
import_stuff -> 'OBJECT-IDENTITY'
: ensure_ver(2,'$1'), {builtin, 'OBJECT-IDENTITY'}.
import_stuff -> 'TEXTUAL-CONVENTION'
: ensure_ver(2,'$1'), {builtin, 'TEXTUAL-CONVENTION'}.
import_stuff -> 'DisplayString'
: ensure_ver(2,'$1'), {builtin, 'DisplayString'}.
import_stuff -> 'PhysAddress'
: ensure_ver(2,'$1'), {builtin, 'PhysAddress'}.
import_stuff -> 'MacAddress'
: ensure_ver(2,'$1'), {builtin, 'MacAddress'}.
import_stuff -> 'TruthValue'
: ensure_ver(2,'$1'), {builtin, 'TruthValue'}.
import_stuff -> 'TestAndIncr'
: ensure_ver(2,'$1'), {builtin, 'TestAndIncr'}.
import_stuff -> 'AutonomousType'
: ensure_ver(2,'$1'), {builtin, 'AutonomousType'}.
import_stuff -> 'InstancePointer'
: ensure_ver(2,'$1'), {builtin, 'InstancePointer'}.
import_stuff -> 'VariablePointer'
: ensure_ver(2,'$1'), {builtin, 'VariablePointer'}.
import_stuff -> 'RowPointer'
: ensure_ver(2,'$1'), {builtin, 'RowPointer'}.
import_stuff -> 'RowStatus'
: ensure_ver(2,'$1'), {builtin, 'RowStatus'}.
import_stuff -> 'TimeStamp'
: ensure_ver(2,'$1'), {builtin, 'TimeStamp'}.
import_stuff -> 'TimeInterval'
: ensure_ver(2,'$1'), {builtin, 'TimeInterval'}.
import_stuff -> 'DateAndTime'
: ensure_ver(2,'$1'), {builtin, 'DateAndTime'}.
import_stuff -> 'StorageType'
: ensure_ver(2,'$1'), {builtin, 'StorageType'}.
import_stuff -> 'TDomain'
: ensure_ver(2,'$1'), {builtin, 'TDomain'}.
import_stuff -> 'TAddress'
: ensure_ver(2,'$1'), {builtin, 'TAddress'}.
import_stuff -> 'BITS'
: ensure_ver(2,'$1'), {builtin, 'BITS'}.
traptype -> objectname 'TRAP-TYPE' 'ENTERPRISE' objectname varpart
description referpart implies integer :
Trap = make_trap('$1', '$4', lreverse(traptype, '$5'),
'$6', '$7', val('$9')),
{Trap, line_of('$2')}.
% defines a name to an internal node.
objectidentifier -> objectname 'OBJECT' 'IDENTIFIER' nameassign :
{Parent, SubIndex} = '$4',
Int = make_internal('$1', dummy, Parent, SubIndex),
{Int, line_of('$2')}.
% defines name, access and type for a variable.
objecttypev1 -> objectname 'OBJECT-TYPE'
'SYNTAX' syntax
'ACCESS' accessv1
'STATUS' statusv1
'DESCRIPTION' descriptionfield
referpart indexpartv1 defvalpart
nameassign :
Kind = kind('$13', '$12'),
OT = make_object_type('$1', '$4', '$6', '$8', '$10',
'$11', Kind, '$14'),
{OT, line_of('$2')}.
newtype -> newtypename implies syntax :
NT = make_new_type('$1', dummy, '$3'),
{NT, line_of('$2')}.
tableentrydefinition -> newtypename implies 'SEQUENCE' '{' fields '}' :
Seq = make_sequence('$1', lreverse(tableentrydefinition, '$5')),
{Seq, line_of('$3')}.
% returns: list of {<fieldname>, <asn1_type>}
fields -> fieldname fsyntax :
[{val('$1'), '$2'}].
fields -> fields ',' fieldname fsyntax : [{val('$3'), '$4'} | '$1'].
fsyntax -> 'BITS' : {{bits,[{dummy,0}]},line_of('$1')}.
fsyntax -> syntax : '$1'.
fieldname -> atom : '$1'.
syntax -> usertype : {{type, val('$1')}, line_of('$1')}.
syntax -> type : {{type, cat('$1')},line_of('$1')}.
syntax -> type size : {{type_with_size, cat('$1'), '$2'},line_of('$1')}.
syntax -> usertype size : {{type_with_size,val('$1'), '$2'},line_of('$1')}.
syntax -> 'INTEGER' '{' namedbits '}' :
{{integer_with_enum, 'INTEGER', '$3'}, line_of('$1')}.
syntax -> 'BITS' '{' namedbits '}' :
ensure_ver(2,'$1'),
{{bits, '$3'}, line_of('$1')}.
syntax -> 'SEQUENCE' 'OF' usertype :
{{sequence_of,val('$3')},line_of('$1')}.
size -> '(' sizedescr ')' : make_range('$2').
size -> '(' 'SIZE' '(' sizedescr ')' ')' : make_range('$4').
%% Returns a list of integers describing a range.
sizedescr -> range_num '.' '.' range_num : ['$1', '$4'].
sizedescr -> range_num '.' '.' range_num sizedescr :['$1', '$4' |'$5'].
sizedescr -> range_num : ['$1'].
sizedescr -> sizedescr '|' sizedescr : ['$1', '$3'].
range_num -> integer : val('$1') .
range_num -> quote atom : make_range_integer(val('$1'), val('$2')) .
range_num -> quote variable : make_range_integer(val('$1'), val('$2')) .
namedbits -> atom '(' integer ')' : [{val('$1'), val('$3')}].
namedbits -> namedbits ',' atom '(' integer ')' :
[{val('$3'), val('$5')} | '$1'].
usertype -> variable : '$1'.
type -> 'OCTET' 'STRING' : {'OCTET STRING', line_of('$1')}.
type -> 'BIT' 'STRING' : {'BIT STRING', line_of('$1')}.
type -> 'OBJECT' 'IDENTIFIER' : {'OBJECT IDENTIFIER', line_of('$1')}.
type -> 'INTEGER' : '$1'.
type -> 'NetworkAddress' : '$1'.
type -> 'IpAddress' : '$1'.
type -> 'Counter' : ensure_ver(1,'$1'),'$1'.
type -> 'Gauge' : ensure_ver(1,'$1'),'$1'.
type -> 'TimeTicks' : '$1'.
type -> 'Opaque' : '$1'.
type -> 'DisplayString' : ensure_ver(2,'$1'), '$1'.
type -> 'PhysAddress' : ensure_ver(2,'$1'), '$1'.
type -> 'MacAddress' : ensure_ver(2,'$1'), '$1'.
type -> 'TruthValue' : ensure_ver(2,'$1'), '$1'.
type -> 'TestAndIncr' : ensure_ver(2,'$1'), '$1'.
type -> 'AutonomousType' : ensure_ver(2,'$1'), '$1'.
type -> 'InstancePointer' : ensure_ver(2,'$1'), '$1'.
type -> 'VariablePointer' : ensure_ver(2,'$1'), '$1'.
type -> 'RowPointer' : ensure_ver(2,'$1'), '$1'.
type -> 'RowStatus' : ensure_ver(2,'$1'), '$1'.
type -> 'TimeStamp' : ensure_ver(2,'$1'), '$1'.
type -> 'TimeInterval' : ensure_ver(2,'$1'), '$1'.
type -> 'DateAndTime' : ensure_ver(2,'$1'), '$1'.
type -> 'StorageType' : ensure_ver(2,'$1'), '$1'.
type -> 'TDomain' : ensure_ver(2,'$1'), '$1'.
type -> 'TAddress' : ensure_ver(2,'$1'), '$1'.
% Returns: {FatherName, SubIndex} (the parent)
nameassign -> implies '{' fatherobjectname parentintegers '}' : {'$3', '$4' }.
nameassign -> implies '{' parentintegers '}' : { root, '$3'}.
varpart -> '$empty' : [].
varpart -> 'VARIABLES' '{' variables '}' : '$3'.
variables -> objectname : ['$1'].
variables -> variables ',' objectname : ['$3' | '$1'].
implies -> '::=' : '$1'.
implies -> ':' ':' '=' : w("Sloppy asignment on line ~p", [line_of('$1')]), '$1'.
descriptionfield -> string : lreverse(descriptionfield, val('$1')).
descriptionfield -> '$empty' : undefined.
description -> 'DESCRIPTION' string : lreverse(description, val('$2')).
description -> '$empty' : undefined.
displaypart -> 'DISPLAY-HINT' string : display_hint('$2') .
displaypart -> '$empty' : undefined .
% returns: {indexes, undefined}
% | {indexes, IndexList} where IndexList is a list of aliasnames.
indexpartv1 -> 'INDEX' '{' indextypesv1 '}' : {indexes, lreverse(indexpartv1, '$3')}.
indexpartv1 -> '$empty' : {indexes, undefined}.
indextypesv1 -> indextypev1 : ['$1'].
indextypesv1 -> indextypesv1 ',' indextypev1 : ['$3' | '$1'].
indextypev1 -> index : '$1'.
index -> objectname : '$1'.
parentintegers -> integer : [val('$1')].
parentintegers -> atom '(' integer ')' : [val('$3')].
parentintegers -> integer parentintegers : [val('$1') | '$2'].
parentintegers -> atom '(' integer ')' parentintegers : [val('$3') | '$5'].
defvalpart -> 'DEFVAL' '{' integer '}' : {defval, val('$3')}.
defvalpart -> 'DEFVAL' '{' atom '}' : {defval, val('$3')}.
defvalpart -> 'DEFVAL' '{' '{' defbitsvalue '}' '}' : {defval, '$4'}.
defvalpart -> 'DEFVAL' '{' quote atom '}' :
{defval, make_defval_for_string(line_of('$1'),
lreverse(defvalpart_quote_atom, val('$3')),
val('$4'))}.
defvalpart -> 'DEFVAL' '{' quote variable '}' :
{defval, make_defval_for_string(line_of('$1'),
lreverse(defvalpart_quote_variable, val('$3')),
val('$4'))}.
defvalpart -> 'DEFVAL' '{' string '}' :
{defval, lreverse(defvalpart_string, val('$3'))}.
defvalpart -> '$empty' : undefined.
defbitsvalue -> defbitsnames : '$1'.
defbitsvalue -> '$empty' : [].
defbitsnames -> atom : [val('$1')].
defbitsnames -> defbitsnames ',' atom : [val('$3') | '$1'].
objectname -> atom : val('$1').
mibname -> variable : val('$1').
fatherobjectname -> objectname : '$1'.
newtypename -> variable : val('$1').
accessv1 -> atom: accessv1('$1').
statusv1 -> atom : statusv1('$1').
referpart -> 'REFERENCE' string : lreverse(referpart, val('$2')).
referpart -> '$empty' : undefined.
%%----------------------------------------------------------------------
%% SNMPv2 grammatics
%%v2
%%----------------------------------------------------------------------
moduleidentity -> mibid 'MODULE-IDENTITY'
'LAST-UPDATED' last_updated
'ORGANIZATION' organization
'CONTACT-INFO' contact_info
'DESCRIPTION' descriptionfield
revisionpart nameassign :
MI = make_module_identity('$1', '$4', '$6', '$8',
'$10', '$11', '$12'),
{MI, line_of('$2')}.
mibid -> atom : val('$1').
last_updated -> string : lreverse(last_updated, val('$1')) .
organization -> string : lreverse(organization, val('$1')) .
contact_info -> string : lreverse(contact_info, val('$1')) .
revisionpart -> '$empty' : [] .
revisionpart -> revisions : lreverse(revisionpart, '$1') .
revisions -> revision : ['$1'] .
revisions -> revisions revision : ['$2' | '$1'] .
revision -> 'REVISION' revision_string 'DESCRIPTION' revision_desc :
make_revision('$2', '$4') .
revision_string -> string : lreverse(revision_string, val('$1')) .
revision_desc -> string : lreverse(revision_desc, val('$1')) .
definitionv2 -> objectidentifier : '$1'.
definitionv2 -> objecttypev2 : '$1'.
definitionv2 -> textualconvention : '$1'.
definitionv2 -> objectidentity : '$1'.
definitionv2 -> newtype : '$1'.
definitionv2 -> tableentrydefinition : '$1'.
definitionv2 -> notification : '$1'.
definitionv2 -> objectgroup : '$1'.
definitionv2 -> notificationgroup : '$1'.
definitionv2 -> modulecompliance : '$1'.
definitionv2 -> agentcapabilities : '$1'.
listofdefinitionsv2 -> '$empty' : [] .
listofdefinitionsv2 -> listofdefinitionsv2 definitionv2 : ['$2' | '$1'].
textualconvention -> newtypename implies 'TEXTUAL-CONVENTION' displaypart
'STATUS' statusv2 description referpart 'SYNTAX' syntax :
NT = make_new_type('$1', 'TEXTUAL-CONVENTION', '$4',
'$6', '$7', '$8', '$10'),
{NT, line_of('$3')}.
objectidentity -> objectname 'OBJECT-IDENTITY' 'STATUS' statusv2
'DESCRIPTION' string referpart nameassign :
{Parent, SubIndex} = '$8',
Int = make_internal('$1', 'OBJECT-IDENTITY',
Parent, SubIndex),
{Int, line_of('$2')}.
objectgroup -> objectname 'OBJECT-GROUP' objectspart
'STATUS' statusv2 description referpart nameassign :
OG = make_object_group('$1', '$3', '$5', '$6', '$7', '$8'),
{OG, line_of('$2')}.
notificationgroup -> objectname 'NOTIFICATION-GROUP' 'NOTIFICATIONS' '{'
objects '}' 'STATUS' statusv2 description referpart
nameassign :
NG = make_notification_group('$1', '$5', '$8', '$9',
'$10', '$11'),
{NG, line_of('$2')}.
modulecompliance -> objectname 'MODULE-COMPLIANCE' 'STATUS' statusv2
description referpart mc_modulepart nameassign :
%% io:format("modulecompliance -> "
%% "~n '$1': ~p"
%% "~n '$4': ~p"
%% "~n '$5': ~p"
%% "~n '$6': ~p"
%% "~n '$7': ~p"
%% "~n '$8': ~p"
%% "~n", ['$1', '$4', '$5', '$6', '$7', '$8']),
MC = make_module_compliance('$1', '$4', '$5', '$6',
'$7', '$8'),
%% io:format("modulecompliance -> "
%% "~n MC: ~p"
%% "~n", [MC]),
{MC, line_of('$2')}.
agentcapabilities -> objectname 'AGENT-CAPABILITIES'
'PRODUCT-RELEASE' prodrel
'STATUS' ac_status
description referpart ac_modulepart nameassign :
AC = make_agent_capabilities('$1', '$4', '$6', '$7',
'$8', '$9', '$10'),
{AC, line_of('$2')}.
prodrel -> string : lreverse(prodrel, val('$1')).
ac_status -> atom : ac_status('$1').
ac_modulepart -> ac_modules :
lreverse(ac_modulepart, '$1').
ac_modulepart -> '$empty' :
[].
ac_modules -> ac_module :
['$1'].
ac_modules -> ac_module ac_modules :
['$1' | '$2'].
ac_module -> 'SUPPORTS' ac_modulenamepart 'INCLUDES' '{' objects '}' ac_variationpart :
make_ac_module('$2', '$5', '$7').
ac_modulenamepart -> mibname : '$1'.
ac_modulenamepart -> '$empty' : undefined.
ac_variationpart -> '$empty' :
[].
ac_variationpart -> ac_variations :
lreverse(ac_variationpart, '$1').
ac_variations -> ac_variation :
['$1'].
ac_variations -> ac_variation ac_variations :
['$1' | '$2'].
%% ac_variation -> ac_objectvariation.
%% ac_variation -> ac_notificationvariation.
ac_variation -> 'VARIATION' objectname syntaxpart writesyntaxpart ac_accesspart ac_creationpart defvalpart description :
make_ac_variation('$2', '$3', '$4', '$5', '$6', '$7', '$8').
ac_accesspart -> 'ACCESS' ac_access : '$2'.
ac_accesspart -> '$empty' : undefined.
ac_access -> atom: ac_access('$1').
ac_creationpart -> 'CREATION-REQUIRES' '{' objects '}' :
lreverse(ac_creationpart, '$3').
ac_creationpart -> '$empty' :
[].
mc_modulepart -> '$empty' :
[].
mc_modulepart -> mc_modules :
lreverse(mc_modulepart, '$1').
mc_modules -> mc_module :
['$1'].
mc_modules -> mc_module mc_modules :
['$1' | '$2'].
mc_module -> 'MODULE' mc_modulenamepart mc_mandatorypart mc_compliancepart :
make_mc_module('$2', '$3', '$4').
mc_modulenamepart -> mibname : '$1'.
mc_modulenamepart -> '$empty' : undefined.
mc_mandatorypart -> 'MANDATORY-GROUPS' '{' objects '}' :
lreverse(mc_mandatorypart, '$3').
mc_mandatorypart -> '$empty' :
[].
mc_compliancepart -> mc_compliances :
lreverse(mc_compliancepart, '$1').
mc_compliancepart -> '$empty' :
[].
mc_compliances -> mc_compliance :
['$1'].
mc_compliances -> mc_compliance mc_compliances :
['$1' | '$2'].
mc_compliance -> mc_compliancegroup :
'$1'.
mc_compliance -> mc_object :
'$1'.
mc_compliancegroup -> 'GROUP' objectname description :
make_mc_compliance_group('$2', '$3').
mc_object -> 'OBJECT' objectname syntaxpart writesyntaxpart mc_accesspart description :
make_mc_object('$2', '$3', '$4', '$5', '$6').
syntaxpart -> 'SYNTAX' syntax : '$2'.
syntaxpart -> '$empty' : undefined.
writesyntaxpart -> 'WRITE-SYNTAX' syntax : '$2'.
writesyntaxpart -> '$empty' : undefined.
mc_accesspart -> 'MIN-ACCESS' accessv2 : '$2'.
mc_accesspart -> '$empty' : undefined.
objecttypev2 -> objectname 'OBJECT-TYPE'
'SYNTAX' syntax
unitspart
'MAX-ACCESS' accessv2
'STATUS' statusv2
'DESCRIPTION' descriptionfield
referpart indexpartv2 defvalpart
nameassign :
Kind = kind('$14', '$13'),
OT = make_object_type('$1', '$4', '$5', '$7', '$9',
'$11', '$12', Kind, '$15'),
{OT, line_of('$2')}.
indexpartv2 -> 'INDEX' '{' indextypesv2 '}' : {indexes, lreverse(indexpartv2, '$3')}.
indexpartv2 -> 'AUGMENTS' '{' entry '}' : {augments, '$3'}.
indexpartv2 -> '$empty' : {indexes, undefined}.
indextypesv2 -> indextypev2 : ['$1'].
indextypesv2 -> indextypesv2 ',' indextypev2 : ['$3' | '$1'].
indextypev2 -> 'IMPLIED' index : {implied,'$2'}.
indextypev2 -> index : '$1'.
entry -> objectname : '$1'.
unitspart -> '$empty' : undefined.
unitspart -> 'UNITS' string : units('$2') .
statusv2 -> atom : statusv2('$1').
accessv2 -> atom: accessv2('$1').
notification -> objectname 'NOTIFICATION-TYPE' objectspart
'STATUS' statusv2 'DESCRIPTION' descriptionfield referpart
nameassign :
Not = make_notification('$1','$3','$5', '$7', '$8', '$9'),
{Not, line_of('$2')}.
objectspart -> 'OBJECTS' '{' objects '}' : lreverse(objectspart, '$3').
objectspart -> '$empty' : [].
objects -> objectname : ['$1'].
objects -> objects ',' objectname : ['$3'|'$1'].
%%----------------------------------------------------------------------
Erlang code.
%%----------------------------------------------------------------------
-include("snmp_types.hrl").
-include("snmpc_lib.hrl").
-include("snmpc.hrl").
% value
val(Token) -> element(3, Token).
line_of(Token) -> element(2, Token).
%% category
cat(Token) -> element(1, Token).
statusv1(Tok) ->
case val(Tok) of
mandatory -> mandatory;
optional -> optional;
obsolete -> obsolete;
deprecated -> deprecated;
Else -> return_error(line_of(Tok),
"(statusv1) syntax error before: " ++ atom_to_list(Else))
end.
statusv2(Tok) ->
case val(Tok) of
current -> current;
deprecated -> deprecated;
obsolete -> obsolete;
Else -> return_error(line_of(Tok),
"(statusv2) syntax error before: " ++ atom_to_list(Else))
end.
ac_status(Tok) ->
case val(Tok) of
current -> current;
obsolete -> obsolete;
Else -> return_error(line_of(Tok),
"(ac_status) syntax error before: " ++ atom_to_list(Else))
end.
accessv1(Tok) ->
case val(Tok) of
'read-only' -> 'read-only';
'read-write' -> 'read-write';
'write-only' -> 'write-only';
'not-accessible' -> 'not-accessible';
Else -> return_error(line_of(Tok),
"(accessv1) syntax error before: " ++ atom_to_list(Else))
end.
accessv2(Tok) ->
case val(Tok) of
'not-accessible' -> 'not-accessible';
'accessible-for-notify' -> 'accessible-for-notify';
'read-only' -> 'read-only';
'read-write' -> 'read-write';
'read-create' -> 'read-create';
Else -> return_error(line_of(Tok),
"(accessv2) syntax error before: " ++ atom_to_list(Else))
end.
ac_access(Tok) ->
case val(Tok) of
'not-implemented' -> 'not-implemented'; % only for notifications
'accessible-for-notify' -> 'accessible-for-notify';
'read-only' -> 'read-only';
'read-write' -> 'read-write';
'read-create' -> 'read-create';
'write-only' -> 'write-only'; % for backward-compatibility only
Else -> return_error(line_of(Tok),
"(ac_access) syntax error before: " ++ atom_to_list(Else))
end.
%% ---------------------------------------------------------------------
%% Various basic record build functions
%% ---------------------------------------------------------------------
make_module_identity(Name, LU, Org, CI, Desc, Revs, NA) ->
#mc_module_identity{name = Name,
last_updated = LU,
organization = Org,
contact_info = CI,
description = Desc,
revisions = Revs,
name_assign = NA}.
make_revision(Rev, Desc) ->
#mc_revision{revision = Rev,
description = Desc}.
make_object_type(Name, Syntax, MaxAcc, Status, Desc, Ref, Kind, NA) ->
#mc_object_type{name = Name,
syntax = Syntax,
max_access = MaxAcc,
status = Status,
description = Desc,
reference = Ref,
kind = Kind,
name_assign = NA}.
make_object_type(Name, Syntax, Units, MaxAcc, Status, Desc, Ref, Kind, NA) ->
#mc_object_type{name = Name,
syntax = Syntax,
units = Units,
max_access = MaxAcc,
status = Status,
description = Desc,
reference = Ref,
kind = Kind,
name_assign = NA}.
make_new_type(Name, Macro, Syntax) ->
#mc_new_type{name = Name,
macro = Macro,
syntax = Syntax}.
make_new_type(Name, Macro, DisplayHint, Status, Desc, Ref, Syntax) ->
#mc_new_type{name = Name,
macro = Macro,
status = Status,
description = Desc,
reference = Ref,
display_hint = DisplayHint,
syntax = Syntax}.
make_trap(Name, Ent, Vars, Desc, Ref, Num) ->
#mc_trap{name = Name,
enterprise = Ent,
vars = Vars,
description = Desc,
reference = Ref,
num = Num}.
make_notification(Name, Vars, Status, Desc, Ref, NA) ->
#mc_notification{name = Name,
vars = Vars,
status = Status,
description = Desc,
reference = Ref,
name_assign = NA}.
make_agent_capabilities(Name, ProdRel, Status, Desc, Ref, Mods, NA) ->
#mc_agent_capabilities{name = Name,
product_release = ProdRel,
status = Status,
description = Desc,
reference = Ref,
modules = Mods,
name_assign = NA}.
make_ac_variation(Name,
undefined = _Syntax,
undefined = _WriteSyntax,
Access,
undefined = _Creation,
undefined = _DefVal,
Desc) ->
%% io:format("make_ac_variation -> entry with"
%% "~n Name: ~p"
%% "~n Access: ~p"
%% "~n Desc: ~p"
%% "~n", [Name, Access, Desc]),
#mc_ac_notification_variation{name = Name,
access = Access,
description = Desc};
make_ac_variation(Name, Syntax, WriteSyntax, Access, Creation, DefVal, Desc) ->
%% io:format("make_ac_variation -> entry with"
%% "~n Name: ~p"
%% "~n Syntax: ~p"
%% "~n WriteSyntax: ~p"
%% "~n Access: ~p"
%% "~n Creation: ~p"
%% "~n DefVal: ~p"
%% "~n Desc: ~p"
%% "~n", [Name, Syntax, WriteSyntax, Access, Creation, DefVal, Desc]),
#mc_ac_object_variation{name = Name,
syntax = Syntax,
write_syntax = WriteSyntax,
access = Access,
creation = Creation,
default_value = DefVal,
description = Desc}.
make_ac_module(Name, Grps, Var) ->
#mc_ac_module{name = Name,
groups = Grps,
variation = Var}.
make_module_compliance(Name, Status, Desc, Ref, Mods, NA) ->
#mc_module_compliance{name = Name,
status = Status,
description = Desc,
reference = Ref,
modules = Mods,
name_assign = NA}.
make_mc_module(Name, Mand, Compl) ->
#mc_mc_module{name = Name,
mandatory = Mand,
compliance = Compl}.
make_mc_compliance_group(Name, Desc) ->
#mc_mc_compliance_group{name = Name,
description = Desc}.
make_mc_object(Name, Syntax, WriteSyntax, Access, Desc) ->
#mc_mc_object{name = Name,
syntax = Syntax,
write_syntax = WriteSyntax,
access = Access,
description = Desc}.
make_object_group(Name, Objs, Status, Desc, Ref, NA) ->
#mc_object_group{name = Name,
objects = Objs,
status = Status,
description = Desc,
reference = Ref,
name_assign = NA}.
make_notification_group(Name, Objs, Status, Desc, Ref, NA) ->
#mc_notification_group{name = Name,
objects = Objs,
status = Status,
description = Desc,
reference = Ref,
name_assign = NA}.
make_sequence(Name, Fields) ->
#mc_sequence{name = Name,
fields = Fields}.
make_internal(Name, Macro, Parent, SubIdx) ->
#mc_internal{name = Name,
macro = Macro,
parent = Parent,
sub_index = SubIdx}.
%% ---------------------------------------------------------------------
%%----------------------------------------------------------------------
%% Purpose: Find how much room needs to be allocated for the data type
%% (when sending it in a PDU (the maximum difference will be
%% the size allocated)).
%% This is applicable for OCTET STRINGs and OBJECT IDENTIFIERs.
%%
%% Or : Find the range of integers in the integer list.
%% This is applicable for INTEGERs
%%
%% Arg: A list of integers.
%%----------------------------------------------------------------------
make_range_integer(RevHexStr, h) ->
erlang:list_to_integer(lists:reverse(RevHexStr), 16);
make_range_integer(RevHexStr, 'H') ->
erlang:list_to_integer(lists:reverse(RevHexStr), 16);
make_range_integer(RevBitStr, b) ->
erlang:list_to_integer(lists:reverse(RevBitStr), 2);
make_range_integer(RevBitStr, 'B') ->
erlang:list_to_integer(lists:reverse(RevBitStr), 2);
make_range_integer(RevStr, Base) ->
throw({error, {invalid_base, Base, lists:reverse(RevStr)}}).
make_range(XIntList) ->
IntList = lists:flatten(XIntList),
{range, lists:min(IntList), lists:max(IntList)}.
make_defval_for_string(Line, Str, Atom) ->
case lists:member(Atom, [h, 'H', b, 'B']) of
true ->
case catch make_defval_for_string2(Str, Atom) of
Defval when is_list(Defval) ->
Defval;
{error, ErrStr} ->
snmpc_lib:print_error("Bad DEFVAL ~w string ~p - ~s",
[Atom, Str, ErrStr],
Line),
"";
_Else ->
snmpc_lib:print_error("Bad DEFVAL ~w string ~p",
[Atom, Str],
Line),
""
end;
false ->
snmpc_lib:print_error("Bad DEFVAL string type ~w for ~p",
[Atom, Str],
Line),
""
end.
make_defval_for_string2([], h) -> [];
make_defval_for_string2([X16,X|HexString], h) ->
lists:append(hex_to_bytes(snmpc_misc:to_upper([X16,X])),
make_defval_for_string2(HexString, h));
make_defval_for_string2([_Odd], h) ->
throw({error, "odd number of bytes in hex string"});
make_defval_for_string2(HexString, 'H') ->
make_defval_for_string2(HexString,h);
make_defval_for_string2(BitString, 'B') ->
bits_to_bytes(BitString);
make_defval_for_string2(BitString, b) ->
make_defval_for_string2(BitString, 'B').
bits_to_bytes(BitStr) ->
lists:reverse(bits_to_bytes(lists:reverse(BitStr), 1, 0)).
bits_to_bytes([], 1, _Byte) -> % empty bitstring
[];
bits_to_bytes([], 256, _Byte) -> % correct; multiple of 8
[];
% If we are to support arbitrary length of bitstrings. This migth
% be needed in the new SMI.
%bits_to_bytes([], N, Byte) ->
% [Byte];
bits_to_bytes([], _N, _Byte) ->
throw({error, "not a multiple of eight bits in bitstring"});
bits_to_bytes(Rest, 256, Byte) ->
[Byte | bits_to_bytes(Rest, 1, 0)];
bits_to_bytes([$1 | T], N, Byte) ->
bits_to_bytes(T, N*2, N + Byte);
bits_to_bytes([$0 | T], N, Byte) ->
bits_to_bytes(T, N*2, Byte);
bits_to_bytes([_BadChar | _T], _N, _Byte) ->
throw({error, "bad character in bit string"}).
%%----------------------------------------------------------------------
%% These HEX conversion routines are stolen from module asn1_bits by
%% [email protected]
%% I didn't want to ship the entire asn1-compiler so I used cut-and-paste.
%%----------------------------------------------------------------------
%% hex_to_bytes(HexNumber) when is_atom(HexNumber) ->
%% hex_to_bytes(atom_to_list(HexNumber));
hex_to_bytes(HexNumber) ->
case length(HexNumber) rem 2 of
1 -> %% Odd
hex_to_bytes(lists:append(HexNumber,[$0]),[]);
0 -> %% even
hex_to_bytes(HexNumber,[])
end.
hex_to_bytes([],R) ->
lists:reverse(R);
hex_to_bytes([Hi,Lo|Rest],Res) ->
hex_to_bytes(Rest,[hex_to_byte(Hi,Lo)|Res]).
hex_to_four_bits(Hex) ->
if
Hex == $0 -> 0;
Hex == $1 -> 1;
Hex == $2 -> 2;
Hex == $3 -> 3;
Hex == $4 -> 4;
Hex == $5 -> 5;
Hex == $6 -> 6;
Hex == $7 -> 7;
Hex == $8 -> 8;
Hex == $9 -> 9;
Hex == $A -> 10;
Hex == $B -> 11;
Hex == $C -> 12;
Hex == $D -> 13;
Hex == $E -> 14;
Hex == $F -> 15;
true -> throw({error, "bad hex character"})
end.
hex_to_byte(Hi,Lo) ->
(hex_to_four_bits(Hi) bsl 4) bor hex_to_four_bits(Lo).
kind(DefValPart,IndexPart) ->
case DefValPart of
undefined ->
case IndexPart of
{indexes, undefined} -> {variable, []};
{indexes, Indexes} ->
{table_entry, {indexes, Indexes}};
{augments,Table} ->
{table_entry,{augments,Table}}
end;
{defval, DefVal} -> {variable, [{defval, DefVal}]}
end.
display_hint(Val) ->
case val(Val) of
Str when is_list(Str) ->
lists:reverse(Str);
_ ->
throw({error, {invalid_display_hint, Val}})
end.
units(Val) ->
case val(Val) of
Str when is_list(Str) ->
lists:reverse(Str);
_ ->
throw({error, {invalid_units, Val}})
end.
ensure_ver(Ver, Line, What) ->
case get(snmp_version) of
Ver -> ok;
_Other ->
snmpc_lib:print_error(
"~s is only allowed in SNMPv~p.",[What,Ver],Line)
end.
ensure_ver(Ver,Token) ->
ensure_ver(Ver,line_of(Token), atom_to_list(cat(Token))).
filter_v2imports(2,'Integer32') -> {builtin, 'Integer32'};
filter_v2imports(2,'Counter32') -> {builtin, 'Counter32'};
filter_v2imports(2,'Gauge32') -> {builtin, 'Gauge32'};
filter_v2imports(2,'Unsigned32') -> {builtin, 'Unsigned32'};
filter_v2imports(2,'Counter64') -> {builtin, 'Counter64'};
filter_v2imports(_,Type) -> {type, Type}.
w(F, A) ->
?vwarning(F, A).
lreverse(_Tag, L) when is_list(L) ->
lists:reverse(L);
lreverse(Tag, X) ->
exit({bad_list, Tag, X}).
%% i(F, A) ->
%% io:format("~w:" ++ F ++ "~n", [?MODULE|A]).