1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%----------------------------------------------------------------------
22%% Number of expected shift/reduce warnings
23%% This is ugly but...
24%%----------------------------------------------------------------------
25
26Expect 2.
27
28
29%% ----------------------------------------------------------------------
30Nonterminals
31%% ----------------------------------------------------------------------
32accessv1
33definition
34defvalpart
35description
36descriptionfield
37displaypart
38entry
39namedbits
40fatherobjectname
41fieldname
42fields
43implies
44import
45import_stuff
46imports
47imports_from_one_mib
48index
49indexpartv1
50indextypev1
51indextypesv1
52parentintegers
53listofdefinitions
54listofimports
55mib
56mibname
57nameassign
58newtype
59newtypename
60objectidentifier
61objectname
62objecttypev1
63prodrel
64range_num
65referpart
66size
67sizedescr
68statusv1
69syntax
70tableentrydefinition
71traptype
72type
73usertype
74variables
75varpart
76
77%v2
78moduleidentity
79revisionpart
80revisions
81listofdefinitionsv2
82mibid
83last_updated
84organization
85contact_info
86revision
87revision_string
88revision_desc
89v1orv2
90objectidentity
91objecttypev2
92unitspart
93indexpartv2
94indextypesv2
95indextypev2
96statusv2
97accessv2
98notification
99objectspart
100objects
101definitionv2
102textualconvention
103objectgroup
104notificationgroup
105modulecompliance
106mc_modulepart
107mc_modules
108mc_module
109mc_modulenamepart
110mc_mandatorypart
111mc_compliancepart
112mc_compliances
113mc_compliance
114mc_compliancegroup
115mc_object
116mc_accesspart
117agentcapabilities
118ac_status
119ac_modulepart
120ac_modules
121ac_module
122ac_modulenamepart
123ac_variationpart
124ac_variations
125ac_variation
126ac_accesspart
127ac_access
128ac_creationpart
129syntaxpart
130writesyntaxpart
131fsyntax
132defbitsvalue
133defbitsnames
134.
135%% ----------------------------------------------------------------------
136Terminals
137%% ----------------------------------------------------------------------
138integer variable atom string quote '{' '}' '::=' ':' '=' ',' '.' '(' ')' ';' '|'
139'ACCESS'
140'BEGIN'
141'BIT'
142'Counter'
143'DEFINITIONS'
144'DEFVAL'
145'DESCRIPTION'
146'DISPLAY-HINT'
147'END'
148'ENTERPRISE'
149'FROM'
150'Gauge'
151'IDENTIFIER'
152'IMPORTS'
153'INDEX'
154'INTEGER'
155'IpAddress'
156'NetworkAddress'
157'OBJECT'
158'OBJECT-TYPE'
159'OCTET'
160'OF'
161'Opaque'
162'REFERENCE'
163'SEQUENCE'
164'SIZE'
165'STATUS'
166'STRING'
167'SYNTAX'
168'TRAP-TYPE'
169'TimeTicks'
170'VARIABLES'
171
172%v2
173'LAST-UPDATED'
174'ORGANIZATION'
175'CONTACT-INFO'
176'MODULE-IDENTITY'
177'NOTIFICATION-TYPE'
178'PRODUCT-RELEASE'
179'AGENT-CAPABILITIES'
180'INCLUDES'
181'SUPPORTS'
182'VARIATION'
183'CREATION-REQUIRES'
184'MODULE-COMPLIANCE'
185'OBJECT-GROUP'
186'NOTIFICATION-GROUP'
187'REVISION'
188'OBJECT-IDENTITY'
189'MAX-ACCESS'
190'UNITS'
191'AUGMENTS'
192'IMPLIED'
193'OBJECTS'
194'TEXTUAL-CONVENTION'
195'NOTIFICATIONS'
196'MODULE'
197'MANDATORY-GROUPS'
198'GROUP'
199'WRITE-SYNTAX'
200'MIN-ACCESS'
201'BITS'
202'DisplayString'
203'PhysAddress'
204'MacAddress'
205'TruthValue'
206'TestAndIncr'
207'AutonomousType'
208'InstancePointer'
209'VariablePointer'
210'RowPointer'
211'RowStatus'
212'TimeStamp'
213'TimeInterval'
214'DateAndTime'
215'StorageType'
216'TDomain'
217'TAddress'
218.
219
220
221Rootsymbol mib.
222Endsymbol '$end'.
223
224% **********************************************************************
225
226mib -> mibname 'DEFINITIONS' implies 'BEGIN'
227       import v1orv2 'END'
228    : {Version, Defs} = '$6',
229      #pdata{mib_version = Version,
230             mib_name    = '$1',
231             imports     = '$5',
232             defs        = Defs}.
233
234v1orv2 -> moduleidentity listofdefinitionsv2 :
235			  {v2_mib, ['$1'|lreverse(v1orv2_mod, '$2')]}.
236v1orv2 -> listofdefinitions : {v1_mib, lreverse(v1orv2_list, '$1')}.
237
238definition -> objectidentifier : '$1'.
239definition -> objecttypev1 : '$1'.
240definition -> newtype : '$1'.
241definition -> tableentrydefinition : '$1'.
242definition -> traptype : '$1'.
243
244listofdefinitions -> definition : ['$1'] .
245listofdefinitions -> listofdefinitions definition : ['$2' | '$1'].
246
247import -> '$empty' : [].
248import -> 'IMPORTS' imports ';' :
249%%           i("import ->"
250%% 	    "~n   imports: ~p", ['$2']),
251          '$2'.
252
253imports -> imports_from_one_mib :
254%%            i("imports ->"
255%%              "~n   imports_from_one_mib: ~p", ['$1']),
256           ['$1'].
257imports -> imports_from_one_mib imports :
258%%            i("imports ->"
259%%              "~n   imports_from_one_mib: ~p"
260%%              "~n   imports:              ~p", ['$1', '$2']),
261           ['$1' | '$2'].
262
263imports_from_one_mib -> listofimports 'FROM' variable :
264%%                         i("imports_from_one_mib ->"
265%%                           "~n   listofimports: ~p"
266%%                           "~n   variable:      ~p", ['$1', '$3']),
267                        {{val('$3'), lreverse(imports_from_one_mib, '$1')}, line_of('$2')}.
268
269listofimports -> import_stuff :
270%%                  i("listofimports ->"
271%%                    "~n   import_stuff: ~p", ['$1']),
272                 ['$1'].
273listofimports -> listofimports ',' import_stuff :
274%%                  i("listofimports ->"
275%%                    "~n   listofimports: ~p"
276%%                    "~n   import_stuff:  ~p", ['$1', '$3']),
277                 ['$3' | '$1'].
278
279import_stuff -> 'OBJECT-TYPE' : {builtin, 'OBJECT-TYPE'}.
280import_stuff -> 'TRAP-TYPE' : {builtin, 'TRAP-TYPE'}.
281import_stuff -> 'NetworkAddress' : {builtin, 'NetworkAddress'}.
282import_stuff -> 'TimeTicks' : {builtin, 'TimeTicks'}.
283import_stuff -> 'IpAddress' : {builtin, 'IpAddress'}.
284import_stuff -> 'Counter' : {builtin, 'Counter'}.
285import_stuff -> 'Gauge' : {builtin, 'Gauge'}.
286import_stuff -> 'Opaque' : {builtin, 'Opaque'}.
287import_stuff -> variable : filter_v2imports(get(snmp_version), val('$1')).
288import_stuff -> atom : {node, val('$1')}.
289%%v2
290import_stuff -> 'MODULE-IDENTITY'
291       : ensure_ver(2,'$1'), {builtin, 'MODULE-IDENTITY'}.
292import_stuff -> 'NOTIFICATION-TYPE'
293       : ensure_ver(2,'$1'), {builtin, 'NOTIFICATION-TYPE'}.
294import_stuff -> 'AGENT-CAPABILITIES'
295       : ensure_ver(2,'$1'), {builtin, 'AGENT-CAPABILITIES'}.
296import_stuff -> 'MODULE-COMPLIANCE'
297       : ensure_ver(2,'$1'), {builtin, 'MODULE-COMPLIANCE'}.
298import_stuff -> 'NOTIFICATION-GROUP'
299       : ensure_ver(2,'$1'), {builtin, 'NOTIFICATION-GROUP'}.
300import_stuff -> 'OBJECT-GROUP'
301       : ensure_ver(2,'$1'), {builtin, 'OBJECT-GROUP'}.
302import_stuff -> 'OBJECT-IDENTITY'
303       : ensure_ver(2,'$1'), {builtin, 'OBJECT-IDENTITY'}.
304import_stuff -> 'TEXTUAL-CONVENTION'
305       : ensure_ver(2,'$1'), {builtin, 'TEXTUAL-CONVENTION'}.
306import_stuff -> 'DisplayString'
307       : ensure_ver(2,'$1'), {builtin, 'DisplayString'}.
308import_stuff -> 'PhysAddress'
309       : ensure_ver(2,'$1'), {builtin, 'PhysAddress'}.
310import_stuff -> 'MacAddress'
311       : ensure_ver(2,'$1'), {builtin, 'MacAddress'}.
312import_stuff -> 'TruthValue'
313       : ensure_ver(2,'$1'), {builtin, 'TruthValue'}.
314import_stuff -> 'TestAndIncr'
315       : ensure_ver(2,'$1'), {builtin, 'TestAndIncr'}.
316import_stuff -> 'AutonomousType'
317       : ensure_ver(2,'$1'), {builtin, 'AutonomousType'}.
318import_stuff -> 'InstancePointer'
319       : ensure_ver(2,'$1'), {builtin, 'InstancePointer'}.
320import_stuff -> 'VariablePointer'
321       : ensure_ver(2,'$1'), {builtin, 'VariablePointer'}.
322import_stuff -> 'RowPointer'
323       : ensure_ver(2,'$1'), {builtin, 'RowPointer'}.
324import_stuff -> 'RowStatus'
325       : ensure_ver(2,'$1'), {builtin, 'RowStatus'}.
326import_stuff -> 'TimeStamp'
327       : ensure_ver(2,'$1'), {builtin, 'TimeStamp'}.
328import_stuff -> 'TimeInterval'
329       : ensure_ver(2,'$1'), {builtin, 'TimeInterval'}.
330import_stuff -> 'DateAndTime'
331       : ensure_ver(2,'$1'), {builtin, 'DateAndTime'}.
332import_stuff -> 'StorageType'
333       : ensure_ver(2,'$1'), {builtin, 'StorageType'}.
334import_stuff -> 'TDomain'
335       : ensure_ver(2,'$1'), {builtin, 'TDomain'}.
336import_stuff -> 'TAddress'
337       : ensure_ver(2,'$1'), {builtin, 'TAddress'}.
338import_stuff -> 'BITS'
339       : ensure_ver(2,'$1'), {builtin, 'BITS'}.
340
341traptype -> objectname 'TRAP-TYPE' 'ENTERPRISE' objectname varpart
342	    description referpart implies integer :
343            Trap = make_trap('$1', '$4', lreverse(traptype, '$5'),
344                             '$6', '$7', val('$9')),
345            {Trap, line_of('$2')}.
346
347% defines a name to an internal node.
348objectidentifier -> objectname 'OBJECT' 'IDENTIFIER' nameassign :
349		    {Parent, SubIndex} = '$4',
350                    Int = make_internal('$1', dummy, Parent, SubIndex),
351		    {Int, line_of('$2')}.
352
353% defines name, access and type for a variable.
354objecttypev1 ->	objectname 'OBJECT-TYPE'
355		'SYNTAX' syntax
356               	'ACCESS' accessv1
357		'STATUS' statusv1
358                'DESCRIPTION' descriptionfield
359		referpart indexpartv1 defvalpart
360		nameassign :
361                Kind = kind('$13', '$12'),
362                OT = make_object_type('$1', '$4', '$6', '$8', '$10',
363                                      '$11', Kind, '$14'),
364                {OT, line_of('$2')}.
365
366newtype -> newtypename implies syntax :
367           NT = make_new_type('$1', dummy, '$3'),
368           {NT, line_of('$2')}.
369
370tableentrydefinition -> newtypename implies 'SEQUENCE' '{' fields '}' :
371                        Seq = make_sequence('$1', lreverse(tableentrydefinition, '$5')),
372                        {Seq, line_of('$3')}.
373
374% returns: list of {<fieldname>, <asn1_type>}
375fields -> fieldname fsyntax :
376	[{val('$1'), '$2'}].
377
378fields -> fields ',' fieldname fsyntax :  [{val('$3'), '$4'} | '$1'].
379
380fsyntax -> 'BITS' : {{bits,[{dummy,0}]},line_of('$1')}.
381fsyntax -> syntax : '$1'.
382
383fieldname -> atom : '$1'.
384
385syntax -> usertype : {{type, val('$1')}, line_of('$1')}.
386syntax -> type : {{type, cat('$1')},line_of('$1')}.
387syntax -> type size : {{type_with_size, cat('$1'), '$2'},line_of('$1')}.
388syntax -> usertype size : {{type_with_size,val('$1'), '$2'},line_of('$1')}.
389syntax -> 'INTEGER' '{' namedbits '}' :
390          {{type_with_enum, 'INTEGER', '$3'}, line_of('$1')}.
391syntax -> 'BITS' '{' namedbits '}' :
392          ensure_ver(2,'$1'),
393          {{bits, '$3'}, line_of('$1')}.
394syntax -> usertype '{' namedbits '}' :
395          {{type_with_enum, 'INTEGER', '$3'}, line_of('$1')}.
396syntax -> 'SEQUENCE' 'OF' usertype :
397          {{sequence_of,val('$3')},line_of('$1')}.
398
399size -> '(' sizedescr ')' : make_range('$2').
400size -> '(' 'SIZE' '(' sizedescr  ')' ')' : make_range('$4').
401
402%% Returns a list of integers describing a range.
403sizedescr -> range_num '.' '.' range_num : ['$1', '$4'].
404sizedescr -> range_num '.' '.' range_num sizedescr :['$1', '$4' |'$5'].
405sizedescr -> range_num : ['$1'].
406sizedescr -> sizedescr '|' sizedescr : ['$1', '$3'].
407
408range_num -> integer : val('$1') .
409range_num -> quote atom  : make_range_integer(val('$1'), val('$2')) .
410range_num -> quote variable  : make_range_integer(val('$1'), val('$2')) .
411
412namedbits -> atom '(' integer ')' : [{val('$1'), val('$3')}].
413namedbits -> namedbits ',' atom '(' integer ')' :
414		 [{val('$3'), val('$5')} | '$1'].
415
416usertype -> variable : '$1'.
417
418type -> 'OCTET' 'STRING' : {'OCTET STRING', line_of('$1')}.
419type -> 'BIT' 'STRING' : {'BIT STRING', line_of('$1')}.
420type -> 'OBJECT' 'IDENTIFIER' : {'OBJECT IDENTIFIER', line_of('$1')}.
421type -> 'INTEGER' : '$1'.
422type -> 'NetworkAddress' : '$1'.
423type -> 'IpAddress' : '$1'.
424type -> 'Counter' : ensure_ver(1,'$1'),'$1'.
425type -> 'Gauge' : ensure_ver(1,'$1'),'$1'.
426type -> 'TimeTicks' : '$1'.
427type -> 'Opaque' : '$1'.
428type -> 'DisplayString' : ensure_ver(2,'$1'), '$1'.
429type -> 'PhysAddress' : ensure_ver(2,'$1'), '$1'.
430type -> 'MacAddress' : ensure_ver(2,'$1'), '$1'.
431type -> 'TruthValue' : ensure_ver(2,'$1'), '$1'.
432type -> 'TestAndIncr' : ensure_ver(2,'$1'), '$1'.
433type -> 'AutonomousType' : ensure_ver(2,'$1'), '$1'.
434type -> 'InstancePointer' : ensure_ver(2,'$1'), '$1'.
435type -> 'VariablePointer' : ensure_ver(2,'$1'), '$1'.
436type -> 'RowPointer' : ensure_ver(2,'$1'), '$1'.
437type -> 'RowStatus' : ensure_ver(2,'$1'), '$1'.
438type -> 'TimeStamp' : ensure_ver(2,'$1'), '$1'.
439type -> 'TimeInterval' : ensure_ver(2,'$1'), '$1'.
440type -> 'DateAndTime' : ensure_ver(2,'$1'), '$1'.
441type -> 'StorageType' : ensure_ver(2,'$1'), '$1'.
442type -> 'TDomain' : ensure_ver(2,'$1'), '$1'.
443type -> 'TAddress' : ensure_ver(2,'$1'), '$1'.
444
445% Returns: {FatherName, SubIndex}   (the parent)
446nameassign -> implies '{' fatherobjectname parentintegers '}' : {'$3', '$4' }.
447nameassign -> implies '{' parentintegers '}' : { root, '$3'}.
448
449
450varpart -> '$empty' : [].
451varpart -> 'VARIABLES' '{' variables '}' : '$3'.
452variables -> objectname : ['$1'].
453variables -> variables ',' objectname : ['$3' | '$1'].
454
455implies -> '::=' : '$1'.
456implies -> ':' ':' '=' : w("Sloppy asignment on line ~p", [line_of('$1')]), '$1'.
457descriptionfield -> string : lreverse(descriptionfield, val('$1')).
458descriptionfield -> '$empty' : undefined.
459description -> 'DESCRIPTION' string : lreverse(description, val('$2')).
460description -> '$empty' : undefined.
461
462displaypart -> 'DISPLAY-HINT' string : display_hint('$2') .
463displaypart -> '$empty' : undefined .
464
465% returns: {indexes, undefined}
466%        | {indexes, IndexList} where IndexList is a list of aliasnames.
467indexpartv1 -> 'INDEX' '{' indextypesv1 '}' : {indexes, lreverse(indexpartv1, '$3')}.
468indexpartv1 -> '$empty' : {indexes, undefined}.
469
470indextypesv1 -> indextypev1 : ['$1'].
471indextypesv1 -> indextypesv1 ',' indextypev1 : ['$3' | '$1'].
472
473indextypev1 ->  index : '$1'.
474
475index -> objectname : '$1'.
476
477parentintegers -> integer : [val('$1')].
478parentintegers -> atom '(' integer ')' : [val('$3')].
479parentintegers -> integer parentintegers : [val('$1') | '$2'].
480parentintegers -> atom '(' integer ')' parentintegers : [val('$3') | '$5'].
481
482defvalpart -> 'DEFVAL' '{' integer '}' : {defval, val('$3')}.
483defvalpart -> 'DEFVAL' '{' atom '}' : {defval, val('$3')}.
484defvalpart -> 'DEFVAL' '{' '{' defbitsvalue '}' '}' : {defval, '$4'}.
485defvalpart -> 'DEFVAL' '{' quote atom '}' :
486	      {defval, make_defval_for_string(line_of('$1'),
487					      lreverse(defvalpart_quote_atom, val('$3')),
488					      val('$4'))}.
489defvalpart -> 'DEFVAL' '{' quote variable '}' :
490	      {defval, make_defval_for_string(line_of('$1'),
491					      lreverse(defvalpart_quote_variable, val('$3')),
492					      val('$4'))}.
493defvalpart -> 'DEFVAL' '{' string '}' :
494	      {defval, lreverse(defvalpart_string, val('$3'))}.
495defvalpart -> '$empty' : undefined.
496
497defbitsvalue -> defbitsnames : '$1'.
498defbitsvalue -> '$empty' : [].
499
500defbitsnames -> atom  : [val('$1')].
501defbitsnames -> defbitsnames ',' atom  : [val('$3') | '$1'].
502
503objectname -> atom : val('$1').
504mibname -> variable : val('$1').
505fatherobjectname -> objectname : '$1'.
506newtypename -> variable : val('$1').
507
508accessv1 -> atom: accessv1('$1').
509
510statusv1 -> atom : statusv1('$1').
511
512referpart -> 'REFERENCE' string : lreverse(referpart, val('$2')).
513referpart -> '$empty' : undefined.
514
515
516%%----------------------------------------------------------------------
517%% SNMPv2 grammatics
518%%v2
519%%----------------------------------------------------------------------
520moduleidentity -> mibid 'MODULE-IDENTITY'
521                  'LAST-UPDATED' last_updated
522	          'ORGANIZATION' organization
523                  'CONTACT-INFO' contact_info
524	          'DESCRIPTION' descriptionfield
525                  revisionpart nameassign :
526                  MI = make_module_identity('$1', '$4', '$6', '$8',
527                                            '$10', '$11', '$12'),
528                  {MI, line_of('$2')}.
529
530mibid -> atom : val('$1').
531last_updated -> string : lreverse(last_updated, val('$1')) .
532organization -> string : lreverse(organization, val('$1')) .
533contact_info -> string : lreverse(contact_info, val('$1')) .
534
535revisionpart -> '$empty' : [] .
536revisionpart -> revisions : lreverse(revisionpart, '$1') .
537
538revisions -> revision : ['$1'] .
539revisions -> revisions revision : ['$2' | '$1'] .
540revision -> 'REVISION' revision_string 'DESCRIPTION' revision_desc :
541            make_revision('$2', '$4') .
542
543revision_string -> string : lreverse(revision_string, val('$1')) .
544revision_desc   -> string : lreverse(revision_desc, val('$1')) .
545
546definitionv2 -> objectidentifier : '$1'.
547definitionv2 -> objecttypev2 : '$1'.
548definitionv2 -> textualconvention : '$1'.
549definitionv2 -> objectidentity : '$1'.
550definitionv2 -> newtype : '$1'.
551definitionv2 -> tableentrydefinition : '$1'.
552definitionv2 -> notification : '$1'.
553definitionv2 -> objectgroup : '$1'.
554definitionv2 -> notificationgroup : '$1'.
555definitionv2 -> modulecompliance : '$1'.
556definitionv2 -> agentcapabilities : '$1'.
557
558listofdefinitionsv2 -> '$empty' : [] .
559listofdefinitionsv2 -> listofdefinitionsv2 definitionv2 : ['$2' | '$1'].
560
561textualconvention -> newtypename implies 'TEXTUAL-CONVENTION' displaypart
562                     'STATUS' statusv2 description referpart 'SYNTAX' syntax :
563                     NT = make_new_type('$1', 'TEXTUAL-CONVENTION', '$4',
564                                        '$6', '$7', '$8', '$10'),
565                     {NT, line_of('$3')}.
566
567objectidentity -> objectname 'OBJECT-IDENTITY' 'STATUS' statusv2
568                  'DESCRIPTION' string referpart nameassign :
569                  {Parent, SubIndex} = '$8',
570                  Int = make_internal('$1', 'OBJECT-IDENTITY',
571                                      Parent, SubIndex),
572                  {Int, line_of('$2')}.
573
574objectgroup -> objectname 'OBJECT-GROUP' objectspart
575               'STATUS' statusv2 description referpart nameassign :
576               OG = make_object_group('$1', '$3', '$5', '$6', '$7', '$8'),
577	       {OG, line_of('$2')}.
578
579notificationgroup -> objectname 'NOTIFICATION-GROUP' 'NOTIFICATIONS' '{'
580                     objects '}' 'STATUS' statusv2 description referpart
581                     nameassign :
582                     NG = make_notification_group('$1', '$5', '$8', '$9',
583                                                  '$10', '$11'),
584                     {NG, line_of('$2')}.
585
586modulecompliance -> objectname 'MODULE-COMPLIANCE' 'STATUS' statusv2
587                    description referpart mc_modulepart nameassign :
588%% 			io:format("modulecompliance -> "
589%% 				  "~n   '$1': ~p"
590%% 				  "~n   '$4': ~p"
591%% 				  "~n   '$5': ~p"
592%% 				  "~n   '$6': ~p"
593%% 				  "~n   '$7': ~p"
594%% 				  "~n   '$8': ~p"
595%% 				  "~n", ['$1', '$4', '$5', '$6', '$7', '$8']),
596                    MC = make_module_compliance('$1', '$4', '$5', '$6',
597                                                '$7', '$8'),
598%% 			io:format("modulecompliance -> "
599%% 				  "~n   MC: ~p"
600%% 				  "~n", [MC]),
601                    {MC, line_of('$2')}.
602
603
604agentcapabilities -> objectname 'AGENT-CAPABILITIES'
605                     'PRODUCT-RELEASE' prodrel
606                     'STATUS' ac_status
607                     description referpart ac_modulepart nameassign :
608                     AC = make_agent_capabilities('$1', '$4', '$6', '$7',
609                                                  '$8', '$9', '$10'),
610                     {AC, line_of('$2')}.
611
612prodrel -> string : lreverse(prodrel, val('$1')).
613
614ac_status -> atom : ac_status('$1').
615
616ac_modulepart -> ac_modules :
617                 lreverse(ac_modulepart, '$1').
618ac_modulepart -> '$empty' :
619                 [].
620
621ac_modules -> ac_module :
622              ['$1'].
623ac_modules -> ac_module ac_modules :
624              ['$1' | '$2'].
625
626ac_module -> 'SUPPORTS' ac_modulenamepart 'INCLUDES' '{' objects '}' ac_variationpart :
627             make_ac_module('$2', '$5', '$7').
628
629ac_modulenamepart -> mibname : '$1'.
630ac_modulenamepart -> '$empty' : undefined.
631
632ac_variationpart -> '$empty' :
633                    [].
634ac_variationpart -> ac_variations :
635                    lreverse(ac_variationpart, '$1').
636
637ac_variations -> ac_variation :
638                 ['$1'].
639ac_variations -> ac_variation ac_variations :
640                 ['$1' | '$2'].
641
642%% ac_variation -> ac_objectvariation.
643%% ac_variation -> ac_notificationvariation.
644
645ac_variation -> 'VARIATION' objectname syntaxpart writesyntaxpart ac_accesspart ac_creationpart defvalpart description :
646                 make_ac_variation('$2', '$3', '$4', '$5', '$6', '$7', '$8').
647
648ac_accesspart -> 'ACCESS' ac_access : '$2'.
649ac_accesspart -> '$empty' : undefined.
650
651ac_access -> atom: ac_access('$1').
652
653ac_creationpart -> 'CREATION-REQUIRES' '{' objects '}' :
654                   lreverse(ac_creationpart, '$3').
655ac_creationpart -> '$empty'                            :
656                   [].
657
658mc_modulepart -> '$empty'   :
659                 [].
660mc_modulepart -> mc_modules :
661                 lreverse(mc_modulepart, '$1').
662
663mc_modules -> mc_module :
664              ['$1'].
665mc_modules -> mc_module mc_modules :
666              ['$1' | '$2'].
667
668mc_module -> 'MODULE' mc_modulenamepart mc_mandatorypart mc_compliancepart :
669             make_mc_module('$2', '$3', '$4').
670
671mc_modulenamepart -> mibname : '$1'.
672mc_modulenamepart -> '$empty' : undefined.
673
674mc_mandatorypart -> 'MANDATORY-GROUPS' '{' objects '}' :
675                    lreverse(mc_mandatorypart, '$3').
676mc_mandatorypart -> '$empty' :
677                    [].
678
679mc_compliancepart -> mc_compliances :
680                     lreverse(mc_compliancepart, '$1').
681mc_compliancepart -> '$empty'       :
682                     [].
683
684mc_compliances -> mc_compliance :
685                  ['$1'].
686mc_compliances -> mc_compliance mc_compliances :
687                  ['$1' | '$2'].
688
689mc_compliance -> mc_compliancegroup :
690                 '$1'.
691mc_compliance -> mc_object          :
692                 '$1'.
693
694mc_compliancegroup -> 'GROUP' objectname description :
695                      make_mc_compliance_group('$2', '$3').
696
697mc_object -> 'OBJECT' objectname syntaxpart writesyntaxpart mc_accesspart description :
698             make_mc_object('$2', '$3', '$4', '$5', '$6').
699
700syntaxpart -> 'SYNTAX' syntax : '$2'.
701syntaxpart -> '$empty'        : undefined.
702
703writesyntaxpart -> 'WRITE-SYNTAX' syntax : '$2'.
704writesyntaxpart -> '$empty'              : undefined.
705
706mc_accesspart -> 'MIN-ACCESS' accessv2 : '$2'.
707mc_accesspart -> '$empty'              : undefined.
708
709objecttypev2 ->	objectname 'OBJECT-TYPE'
710		'SYNTAX' syntax
711                unitspart
712               	'MAX-ACCESS' accessv2
713		'STATUS' statusv2
714                'DESCRIPTION' descriptionfield
715                referpart indexpartv2 defvalpart
716		nameassign :
717                Kind = kind('$14', '$13'),
718                OT = make_object_type('$1', '$4', '$5', '$7', '$9',
719                                      '$11', '$12', Kind, '$15'),
720                {OT, line_of('$2')}.
721
722indexpartv2 -> 'INDEX' '{' indextypesv2 '}' : {indexes, lreverse(indexpartv2, '$3')}.
723indexpartv2 -> 'AUGMENTS' '{' entry  '}' : {augments, '$3'}.
724indexpartv2 -> '$empty' : {indexes, undefined}.
725
726indextypesv2 -> indextypev2 : ['$1'].
727indextypesv2 -> indextypesv2 ',' indextypev2 : ['$3' | '$1'].
728
729indextypev2 ->  'IMPLIED' index : {implied,'$2'}.
730indextypev2 ->  index : '$1'.
731
732entry -> objectname : '$1'.
733
734unitspart -> '$empty' : undefined.
735unitspart -> 'UNITS' string : units('$2') .
736
737statusv2 -> atom : statusv2('$1').
738
739accessv2 -> atom: accessv2('$1').
740
741notification -> objectname 'NOTIFICATION-TYPE' objectspart
742                'STATUS' statusv2 'DESCRIPTION' descriptionfield referpart
743                nameassign :
744                Not = make_notification('$1','$3','$5', '$7', '$8', '$9'),
745                {Not, line_of('$2')}.
746
747objectspart -> 'OBJECTS' '{' objects '}' : lreverse(objectspart, '$3').
748objectspart -> '$empty' : [].
749
750objects -> objectname : ['$1'].
751objects -> objects ',' objectname : ['$3'|'$1'].
752
753%%----------------------------------------------------------------------
754Erlang code.
755%%----------------------------------------------------------------------
756
757-include("snmp_types.hrl").
758-include("snmpc_lib.hrl").
759-include("snmpc.hrl").
760
761% value
762val(Token) -> element(3, Token).
763
764line_of(Token) -> element(2, Token).
765
766%% category
767cat(Token) -> element(1, Token).
768
769statusv1(Tok) ->
770    case val(Tok) of
771        mandatory -> mandatory;
772        optional -> optional;
773        obsolete -> obsolete;
774        deprecated -> deprecated;
775        Else -> return_error(line_of(Tok),
776                             "(statusv1) syntax error before: " ++ atom_to_list(Else))
777    end.
778
779statusv2(Tok) ->
780    case val(Tok) of
781        current -> current;
782        deprecated -> deprecated;
783        obsolete -> obsolete;
784        Else -> return_error(line_of(Tok),
785                             "(statusv2) syntax error before: " ++ atom_to_list(Else))
786    end.
787
788ac_status(Tok) ->
789    case val(Tok) of
790        current -> current;
791        obsolete -> obsolete;
792        Else -> return_error(line_of(Tok),
793                             "(ac_status) syntax error before: " ++ atom_to_list(Else))
794    end.
795
796accessv1(Tok) ->
797    case val(Tok) of
798        'read-only' -> 'read-only';
799        'read-write' -> 'read-write';
800        'write-only' -> 'write-only';
801        'not-accessible' -> 'not-accessible';
802        Else -> return_error(line_of(Tok),
803                             "(accessv1) syntax error before: " ++ atom_to_list(Else))
804    end.
805
806accessv2(Tok) ->
807    case val(Tok) of
808        'not-accessible' -> 'not-accessible';
809        'accessible-for-notify' -> 'accessible-for-notify';
810        'read-only' -> 'read-only';
811        'read-write' -> 'read-write';
812        'read-create' -> 'read-create';
813        Else -> return_error(line_of(Tok),
814                             "(accessv2) syntax error before: " ++ atom_to_list(Else))
815    end.
816
817ac_access(Tok) ->
818    case val(Tok) of
819        'not-implemented' -> 'not-implemented'; % only for notifications
820        'accessible-for-notify' -> 'accessible-for-notify';
821        'read-only' -> 'read-only';
822        'read-write' -> 'read-write';
823        'read-create' -> 'read-create';
824        'write-only' -> 'write-only'; % for backward-compatibility only
825        Else -> return_error(line_of(Tok),
826                             "(ac_access) syntax error before: " ++ atom_to_list(Else))
827    end.
828
829%% ---------------------------------------------------------------------
830%% Various basic record build functions
831%% ---------------------------------------------------------------------
832
833make_module_identity(Name, LU, Org, CI, Desc, Revs, NA) ->
834    #mc_module_identity{name         = Name,
835                        last_updated = LU,
836	                organization = Org,
837	                contact_info = CI,
838	                description  = Desc,
839	                revisions    = Revs,
840	                name_assign  = NA}.
841
842make_revision(Rev, Desc) ->
843    #mc_revision{revision    = Rev,
844	         description = Desc}.
845
846make_object_type(Name, Syntax, MaxAcc, Status, Desc, Ref, Kind, NA) ->
847    #mc_object_type{name        = Name,
848                    syntax      = Syntax,
849	            max_access  = MaxAcc,
850	            status      = Status,
851	            description = Desc,
852	            reference   = Ref,
853	            kind        = Kind,
854	            name_assign = NA}.
855
856make_object_type(Name, Syntax, Units, MaxAcc, Status, Desc, Ref, Kind, NA) ->
857    #mc_object_type{name        = Name,
858                    syntax      = Syntax,
859                    units       = Units,
860	            max_access  = MaxAcc,
861	            status      = Status,
862	            description = Desc,
863	            reference   = Ref,
864	            kind        = Kind,
865	            name_assign = NA}.
866
867make_new_type(Name, Macro, Syntax) ->
868    #mc_new_type{name   = Name,
869	         macro  = Macro,
870                 syntax = Syntax}.
871
872make_new_type(Name, Macro, DisplayHint, Status, Desc, Ref, Syntax) ->
873    #mc_new_type{name         = Name,
874	         macro        = Macro,
875                 status       = Status,
876                 description  = Desc,
877                 reference    = Ref,
878	         display_hint = DisplayHint,
879                 syntax       = Syntax}.
880
881make_trap(Name, Ent, Vars, Desc, Ref, Num) ->
882    #mc_trap{name        = Name,
883             enterprise  = Ent,
884             vars        = Vars,
885             description = Desc,
886	     reference   = Ref,
887	     num         = Num}.
888
889make_notification(Name, Vars, Status, Desc, Ref, NA) ->
890    #mc_notification{name        = Name,
891                     vars        = Vars,
892                     status      = Status,
893                     description = Desc,
894	             reference   = Ref,
895	             name_assign = NA}.
896
897make_agent_capabilities(Name, ProdRel, Status, Desc, Ref, Mods, NA) ->
898    #mc_agent_capabilities{name            = Name,
899                           product_release = ProdRel,
900                           status          = Status,
901                           description     = Desc,
902	                   reference       = Ref,
903                           modules         = Mods,
904	                   name_assign     = NA}.
905
906make_ac_variation(Name,
907		  undefined = _Syntax,
908		  undefined = _WriteSyntax,
909		  Access,
910		  undefined = _Creation,
911		  undefined = _DefVal,
912		  Desc) ->
913%%     io:format("make_ac_variation -> entry with"
914%% 	      "~n   Name:        ~p"
915%% 	      "~n   Access:      ~p"
916%% 	      "~n   Desc:        ~p"
917%% 	      "~n", [Name, Access, Desc]),
918    #mc_ac_notification_variation{name        = Name,
919 				  access      = Access,
920 				  description = Desc};
921
922make_ac_variation(Name, Syntax, WriteSyntax, Access, Creation, DefVal, Desc) ->
923%%     io:format("make_ac_variation -> entry with"
924%% 	      "~n   Name:        ~p"
925%% 	      "~n   Syntax:      ~p"
926%% 	      "~n   WriteSyntax: ~p"
927%% 	      "~n   Access:      ~p"
928%% 	      "~n   Creation:    ~p"
929%% 	      "~n   DefVal:      ~p"
930%% 	      "~n   Desc:        ~p"
931%% 	      "~n", [Name, Syntax, WriteSyntax, Access, Creation, DefVal, Desc]),
932    #mc_ac_object_variation{name          = Name,
933			    syntax        = Syntax,
934			    write_syntax  = WriteSyntax,
935			    access        = Access,
936			    creation      = Creation,
937			    default_value = DefVal,
938			    description   = Desc}.
939
940make_ac_module(Name, Grps, Var) ->
941    #mc_ac_module{name      = Name,
942		  groups    = Grps,
943		  variation = Var}.
944
945
946make_module_compliance(Name, Status, Desc, Ref, Mods, NA) ->
947    #mc_module_compliance{name        = Name,
948                          status      = Status,
949                          description = Desc,
950	                  reference   = Ref,
951                          modules     = Mods,
952	                  name_assign = NA}.
953
954make_mc_module(Name, Mand, Compl) ->
955    #mc_mc_module{name       = Name,
956		  mandatory  = Mand,
957		  compliance = Compl}.
958
959make_mc_compliance_group(Name, Desc) ->
960    #mc_mc_compliance_group{name        = Name,
961			    description = Desc}.
962
963make_mc_object(Name, Syntax, WriteSyntax, Access, Desc) ->
964    #mc_mc_object{name         = Name,
965		  syntax       = Syntax,
966		  write_syntax = WriteSyntax,
967		  access       = Access,
968		  description  = Desc}.
969
970make_object_group(Name, Objs, Status, Desc, Ref, NA) ->
971    #mc_object_group{name        = Name,
972                     objects     = Objs,
973                     status      = Status,
974                     description = Desc,
975	             reference   = Ref,
976	             name_assign = NA}.
977
978make_notification_group(Name, Objs, Status, Desc, Ref, NA) ->
979    #mc_notification_group{name        = Name,
980                           objects     = Objs,
981                           status      = Status,
982                           description = Desc,
983	                   reference   = Ref,
984	                   name_assign = NA}.
985
986make_sequence(Name, Fields) ->
987    #mc_sequence{name   = Name,
988                 fields = Fields}.
989
990make_internal(Name, Macro, Parent, SubIdx) ->
991    #mc_internal{name      = Name,
992                 macro     = Macro,
993                 parent    = Parent,
994                 sub_index = SubIdx}.
995
996
997
998%% ---------------------------------------------------------------------
999
1000
1001%%----------------------------------------------------------------------
1002%% Purpose: Find how much room needs to be allocated for the data type
1003%%          (when sending it in a PDU (the maximum difference will be
1004%%           the size allocated)).
1005%%          This is applicable for OCTET STRINGs and OBJECT IDENTIFIERs.
1006%%
1007%%     Or : Find the range of integers in the integer list.
1008%%          This is applicable for INTEGERs
1009%%
1010%% Arg: A list of integers.
1011%%----------------------------------------------------------------------
1012
1013make_range_integer(RevHexStr, h) ->
1014    erlang:list_to_integer(lists:reverse(RevHexStr), 16);
1015make_range_integer(RevHexStr, 'H') ->
1016    erlang:list_to_integer(lists:reverse(RevHexStr), 16);
1017make_range_integer(RevBitStr, b) ->
1018    erlang:list_to_integer(lists:reverse(RevBitStr), 2);
1019make_range_integer(RevBitStr, 'B') ->
1020    erlang:list_to_integer(lists:reverse(RevBitStr), 2);
1021make_range_integer(RevStr, Base) ->
1022    throw({error, {invalid_base, Base, lists:reverse(RevStr)}}).
1023
1024make_range(XIntList) ->
1025    IntList = lists:flatten(XIntList),
1026    {range, lists:min(IntList), lists:max(IntList)}.
1027
1028make_defval_for_string(Line, Str, Atom) ->
1029    case lists:member(Atom, [h, 'H', b, 'B']) of
1030	true ->
1031	    case catch make_defval_for_string2(Str, Atom) of
1032		Defval when is_list(Defval) ->
1033		    Defval;
1034		{error, ErrStr} ->
1035		    snmpc_lib:print_error("Bad DEFVAL ~w string ~p - ~s",
1036						 [Atom, Str, ErrStr],
1037						 Line),
1038		    "";
1039		_Else ->
1040		    snmpc_lib:print_error("Bad DEFVAL ~w string ~p",
1041						 [Atom, Str],
1042						 Line),
1043		    ""
1044	    end;
1045	false ->
1046	    snmpc_lib:print_error("Bad DEFVAL string type ~w for ~p",
1047					 [Atom, Str],
1048					 Line),
1049	    ""
1050    end.
1051
1052
1053make_defval_for_string2([], h) -> [];
1054make_defval_for_string2([X16,X|HexString], h) ->
1055    lists:append(hex_to_bytes(snmpc_misc:to_upper([X16,X])),
1056		 make_defval_for_string2(HexString, h));
1057make_defval_for_string2([_Odd], h) ->
1058    throw({error, "odd number of bytes in hex string"});
1059make_defval_for_string2(HexString, 'H') ->
1060    make_defval_for_string2(HexString,h);
1061
1062make_defval_for_string2(BitString, 'B') ->
1063    bits_to_bytes(BitString);
1064make_defval_for_string2(BitString, b) ->
1065    make_defval_for_string2(BitString, 'B').
1066
1067bits_to_bytes(BitStr) ->
1068    lists:reverse(bits_to_bytes(lists:reverse(BitStr), 1, 0)).
1069
1070bits_to_bytes([], 1, _Byte) ->   % empty bitstring
1071    [];
1072bits_to_bytes([], 256, _Byte) -> % correct; multiple of 8
1073    [];
1074% If we are to support arbitrary length of bitstrings.  This migth
1075% be needed in the new SMI.
1076%bits_to_bytes([], N, Byte) ->
1077%    [Byte];
1078bits_to_bytes([], _N, _Byte) ->
1079    throw({error, "not a multiple of eight bits in bitstring"});
1080bits_to_bytes(Rest, 256, Byte) ->
1081    [Byte | bits_to_bytes(Rest, 1, 0)];
1082bits_to_bytes([$1 | T], N, Byte) ->
1083    bits_to_bytes(T, N*2, N + Byte);
1084bits_to_bytes([$0 | T], N, Byte) ->
1085    bits_to_bytes(T, N*2, Byte);
1086bits_to_bytes([_BadChar | _T], _N, _Byte) ->
1087    throw({error, "bad character in bit string"}).
1088
1089%%----------------------------------------------------------------------
1090%% These HEX conversion routines are stolen from module asn1_bits by
1091%% klacke@erix.ericsson.se
1092%% I didn't want to ship the entire asn1-compiler so I used cut-and-paste.
1093%%----------------------------------------------------------------------
1094
1095%% hex_to_bytes(HexNumber) when is_atom(HexNumber) ->
1096%%     hex_to_bytes(atom_to_list(HexNumber));
1097
1098hex_to_bytes(HexNumber) ->
1099    case length(HexNumber) rem 2 of
1100	1 ->  %% Odd
1101	    hex_to_bytes(lists:append(HexNumber,[$0]),[]);
1102	0 ->  %% even
1103	    hex_to_bytes(HexNumber,[])
1104    end.
1105
1106hex_to_bytes([],R) ->
1107    lists:reverse(R);
1108hex_to_bytes([Hi,Lo|Rest],Res) ->
1109    hex_to_bytes(Rest,[hex_to_byte(Hi,Lo)|Res]).
1110
1111hex_to_four_bits(Hex) ->
1112    if
1113	Hex == $0 -> 0;
1114	Hex == $1 -> 1;
1115	Hex == $2 -> 2;
1116	Hex == $3 -> 3;
1117	Hex == $4 -> 4;
1118	Hex == $5 -> 5;
1119	Hex == $6 -> 6;
1120	Hex == $7 -> 7;
1121	Hex == $8 -> 8;
1122	Hex == $9 -> 9;
1123	Hex == $A -> 10;
1124	Hex == $B -> 11;
1125	Hex == $C -> 12;
1126	Hex == $D -> 13;
1127	Hex == $E -> 14;
1128	Hex == $F -> 15;
1129	true -> throw({error, "bad hex character"})
1130    end.
1131
1132hex_to_byte(Hi,Lo) ->
1133    (hex_to_four_bits(Hi) bsl 4) bor hex_to_four_bits(Lo).
1134
1135kind(DefValPart,IndexPart) ->
1136    case DefValPart of
1137	undefined ->
1138	    case IndexPart of
1139		{indexes, undefined} -> {variable, []};
1140		{indexes, Indexes}  ->
1141		    {table_entry, {indexes, Indexes}};
1142		{augments,Table} ->
1143		    {table_entry,{augments,Table}}
1144	    end;
1145	{defval, DefVal} -> {variable, [{defval, DefVal}]}
1146    end.
1147
1148display_hint(Val) ->
1149    case val(Val) of
1150        Str when is_list(Str) ->
1151            lists:reverse(Str);
1152        _ ->
1153            throw({error, {invalid_display_hint, Val}})
1154    end.
1155
1156units(Val) ->
1157    case val(Val) of
1158        Str when is_list(Str) ->
1159            lists:reverse(Str);
1160        _ ->
1161            throw({error, {invalid_units, Val}})
1162    end.
1163
1164ensure_ver(Ver, Line, What) ->
1165    case get(snmp_version) of
1166	Ver -> ok;
1167	_Other ->
1168	    snmpc_lib:print_error(
1169	      "~s is only allowed in SNMPv~p.",[What,Ver],Line)
1170    end.
1171
1172
1173ensure_ver(Ver,Token) ->
1174    ensure_ver(Ver,line_of(Token), atom_to_list(cat(Token))).
1175
1176filter_v2imports(2,'Integer32')  -> {builtin, 'Integer32'};
1177filter_v2imports(2,'Counter32')  -> {builtin, 'Counter32'};
1178filter_v2imports(2,'Gauge32')    -> {builtin, 'Gauge32'};
1179filter_v2imports(2,'Unsigned32') -> {builtin, 'Unsigned32'};
1180filter_v2imports(2,'Counter64')  -> {builtin, 'Counter64'};
1181filter_v2imports(_,Type)         -> {type, Type}.
1182
1183w(F, A) ->
1184    ?vwarning(F, A).
1185
1186lreverse(_Tag, L) when is_list(L) ->
1187    lists:reverse(L);
1188lreverse(Tag, X) ->
1189    exit({bad_list, Tag, X}).
1190
1191
1192%% i(F, A) ->
1193%%     io:format("~w:" ++ F ++ "~n", [?MODULE|A]).
1194
1195