diff options
Diffstat (limited to 'lib/snmp/src/compile/snmpc_mib_gram.yrl')
-rw-r--r-- | lib/snmp/src/compile/snmpc_mib_gram.yrl | 973 |
1 files changed, 973 insertions, 0 deletions
diff --git a/lib/snmp/src/compile/snmpc_mib_gram.yrl b/lib/snmp/src/compile/snmpc_mib_gram.yrl new file mode 100644 index 0000000000..1957f52936 --- /dev/null +++ b/lib/snmp/src/compile/snmpc_mib_gram.yrl @@ -0,0 +1,973 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights 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 +range_num +referpart +size +sizedescr +statusv1 +syntax +tableentrydefinition +traptype +type +usertype +variables +varpart + +%v2 +moduleidentity +revisionpart +revisions +listofdefinitionsv2 +mibid +last_updated +oranization +contact_info +revision +revision_string +revision_desc +v1orv2 +objectidentity +objecttypev2 +unitspart +indexpartv2 +indextypesv2 +indextypev2 +statusv2 +accessv2 +notification +objectspart +objects +definitionv2 +textualconvention +objectgroup +notificationgroup +modulecompliance +modulepart +modules +module +modulenamepart +mandatorypart +compliancepart +compliances +compliance +compliancegroup +object +syntaxpart +writesyntaxpart +accesspart +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' +'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'|lists:reverse('$2')]}. +v1orv2 -> listofdefinitions : {v1_mib, lists:reverse('$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 ';' : '$2'. + +imports -> imports_from_one_mib : ['$1']. +imports -> imports_from_one_mib imports : ['$1' | '$2']. + +imports_from_one_mib -> listofimports 'FROM' variable : + {{val('$3'), lists:reverse('$1')}, line_of('$2')}. + +listofimports -> import_stuff : ['$1']. +listofimports -> listofimports ',' import_stuff : ['$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 -> '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'}. + +traptype -> objectname 'TRAP-TYPE' 'ENTERPRISE' objectname varpart + description referpart implies integer : + Trap = make_trap('$1', '$4', lists:reverse('$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', lists:reverse('$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 : lists:reverse(val('$1')). +descriptionfield -> '$empty' : undefined. +description -> 'DESCRIPTION' string : lists:reverse(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, lists:reverse('$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'), lists:reverse(val('$3')), + val('$4'))}. +defvalpart -> 'DEFVAL' '{' quote variable '}' + : {defval, make_defval_for_string(line_of('$1'), lists:reverse(val('$3')), + val('$4'))}. +defvalpart -> 'DEFVAL' '{' string '}' + : {defval, lists:reverse(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 : lists:reverse(val('$2')). +referpart -> '$empty' : undefined. + + +%%---------------------------------------------------------------------- +%% SNMPv2 grammatics +%%v2 +%%---------------------------------------------------------------------- +moduleidentity -> mibid 'MODULE-IDENTITY' + 'LAST-UPDATED' last_updated + 'ORGANIZATION' oranization + '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 : lists:reverse(val('$1')) . +oranization -> string : lists:reverse(val('$1')) . +contact_info -> string : lists:reverse(val('$1')) . + +revisionpart -> '$empty' : [] . +revisionpart -> revisions : lists:reverse('$1') . + +revisions -> revision : ['$1'] . +revisions -> revisions revision : ['$2' | '$1'] . +revision -> 'REVISION' revision_string 'DESCRIPTION' revision_desc : + make_revision('$2', '$4') . + +revision_string -> string : lists:reverse(val('$1')) . +revision_desc -> string : lists:reverse(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'. + +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 modulepart nameassign : + MC = make_module_compliance('$1', '$4', '$5', '$6', + '$7', '$8'), + {MC, line_of('$2')}. + +modulepart -> '$empty'. +modulepart -> modules. + +modules -> module. +modules -> modules module. + +module -> 'MODULE' modulenamepart mandatorypart compliancepart. + +modulenamepart -> mibname. +modulenamepart -> '$empty'. + +mandatorypart -> 'MANDATORY-GROUPS' '{' objects '}'. +mandatorypart -> '$empty'. + +compliancepart -> compliances. +compliancepart -> '$empty'. + +compliances -> compliance. +compliances -> compliances compliance. + +compliance -> compliancegroup. +compliance -> object. + +compliancegroup -> 'GROUP' objectname description. + +object -> 'OBJECT' objectname syntaxpart writesyntaxpart accesspart description. + +syntaxpart -> 'SYNTAX' syntax. +syntaxpart -> '$empty'. + +writesyntaxpart -> 'WRITE-SYNTAX' syntax. +writesyntaxpart -> '$empty'. + +accesspart -> 'MIN-ACCESS' accessv2. +accesspart -> '$empty'. + +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, lists:reverse('$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 '}' : lists:reverse('$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), + "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), + "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), + "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), + "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_module_compliance(Name, Status, Desc, Ref, Mod, NA) -> + #mc_module_compliance{name = Name, + status = Status, + description = Desc, + reference = Ref, + module = Mod, + name_assign = NA}. + +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 +%% 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). + +%i(F, A) -> +% io:format("~w:" ++ F ++ "~n", [?MODULE|A]). + |