1;;; snmp-mode.el --- SNMP & SNMPv2 MIB major mode
2
3;; Copyright (C) 1995, 1998, 2001, 2002, 2003, 2004,
4;;   2005, 2006, 2007 Free Software Foundation, Inc.
5
6;; Author: Paul D. Smith <psmith@BayNetworks.com>
7;; Keywords: data
8
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs; see the file COPYING.  If not, write to the
23;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24;; Boston, MA 02110-1301, USA.
25
26;;; Commentary:
27
28;; INTRODUCTION
29;; ------------
30;; This package provides a major mode for editing SNMP MIBs.  It
31;; provides all the modern Emacs 19 bells and whistles: default
32;; fontification via font-lock, imenu search functions, etc.
33;;
34;; SNMP mode also uses tempo, a textual boilerplate insertion package
35;; distributed with Emacs, to add in boilerplate SNMP MIB structures.
36;; See tempo.el for more details about tempo.
37;;
38;; If you want to change or add new tempo templates, use the tempo tag
39;; list `snmp-tempo-tags' (or `snmpv2-tempo-tags'): this list is
40;; automatically installed when snmp-mode (or snmpv2-mode) is entered.
41;;
42;; The SNMPv2 mode in this version has been enhanced thanks to popular
43;; demand.
44;;
45;; I'm very interested in new tempo macros for both v1 and v2, and any
46;; other suggestions for enhancements (different syntax table items, new
47;; keybindings, etc.)
48;;
49;;
50;; USAGE
51;; -----
52;; Mostly, use it as you would any other mode.  There's a very
53;; simplistic auto-indent feature; hopefully it'll help more than get in
54;; your way.  For the most part it tries to indent to the same level as
55;; the previous line.  It will try to recognize some very simple tokens
56;; on the previous line that tell it to use extra indent or outdent.
57;;
58;; Templates
59;; ---------
60;; To use the Tempo templates, type the Tempo tag (or a unique prefix)
61;; and use C-c C-i (C-c TAB) to complete it; if you don't have
62;; tempo-interactive set to nil it will ask you to fill in values.
63;; Fields with predefined values (SYNTAX, STATUS, etc.) will do
64;; completing-reads on a list of valid values; use the normal SPC or TAB
65;; to complete.
66;;
67;; Currently the following templates are available:
68;;
69;;  objectType -- Defines an OBJECT-TYPE macro.
70;;
71;;  tableType  -- Defines both a Table and Entry OBJECT-TYPE, and a
72;;                SEQUENCE for the ASN.1 Entry definition.
73;;
74;; Once the template is done, you can use C-cC-f and C-cC-b to move back
75;; and forth between the Tempo sequence points to fill in the rest of
76;; the information.
77;;
78;; Font Lock
79;; ------------
80;;
81;; If you want font-lock in your MIB buffers, add this:
82;;
83;;  (add-hook 'snmp-common-mode-hook 'turn-on-font-lock)
84;;
85;; Enabling global-font-lock-mode is also sufficient.
86;;
87
88;;; Code:
89
90(eval-when-compile
91  (require 'tempo))
92
93;;;----------------------------------------------------------------------------
94;;
95;;                          Customize these:
96;;
97;;;----------------------------------------------------------------------------
98
99(defgroup snmp nil
100  "Mode for editing SNMP MIB files."
101  :group 'data
102  :version "20.4")
103
104(defcustom snmp-special-indent t
105  "*If non-nil, use a simple heuristic to try to guess the right indentation.
106If nil, then no special indentation is attempted."
107  :type 'boolean
108  :group 'snmp)
109
110(defcustom snmp-indent-level 4
111  "*Indentation level for SNMP MIBs."
112  :type 'integer
113  :group 'snmp)
114
115(defcustom snmp-tab-always-indent nil
116  "*Non-nil means TAB should always reindent the current line.
117A value of nil means reindent if point is within the initial line indentation;
118otherwise insert a TAB."
119  :type 'boolean
120  :group 'snmp)
121
122(defcustom snmp-completion-ignore-case t
123  "*Non-nil means that case differences are ignored during completion.
124A value of nil means that case is significant.
125This is used during Tempo template completion."
126  :type 'boolean
127  :group 'snmp)
128
129(defcustom snmp-common-mode-hook nil
130  "*Hook(s) evaluated when a buffer enters either SNMP or SNMPv2 mode."
131  :type 'hook
132  :group 'snmp)
133
134(defcustom snmp-mode-hook nil
135  "*Hook(s) evaluated when a buffer enters SNMP mode."
136  :type 'hook
137  :group 'snmp)
138
139(defcustom snmpv2-mode-hook nil
140  "*Hook(s) evaluated when a buffer enters SNMPv2 mode."
141  :type 'hook
142  :group 'snmp)
143
144(defvar snmp-tempo-tags nil
145  "*Tempo tags for SNMP mode.")
146
147(defvar snmpv2-tempo-tags nil
148  "*Tempo tags for SNMPv2 mode.")
149
150
151;; Enable fontification for SNMP MIBs
152;;
153
154;; These are pretty basic fontifications.  Note we assume these macros
155;; are first on a line (except whitespace), to speed up fontification.
156;;
157(defvar snmp-font-lock-keywords-1
158  (list
159   ;; OBJECT-TYPE, TRAP-TYPE, and OBJECT-IDENTIFIER macros
160   '("^[ \t]*\\([a-z][-a-zA-Z0-9]+\\)[ \t]+\\(\\(MODULE-\\(COMPLIANCE\\|IDENTITY\\)\\|OBJECT-\\(COMPLIANCE\\|GROUP\\|IDENTITY\\|TYPE\\)\\|TRAP-\\(GROUP\\|TYPE\\)\\)\\|\\(OBJECT\\)[ \t]+\\(IDENTIFIER\\)[ \t]*::=\\)"
161     (1 font-lock-variable-name-face) (3 font-lock-keyword-face nil t)
162     (7 font-lock-keyword-face nil t) (8 font-lock-keyword-face nil t))
163
164   ;; DEFINITIONS clause
165   '("^[ \t]*\\([A-Z][-a-zA-Z0-9]+\\)[ \t]+\\(DEFINITIONS\\)[ \t]*::="
166     (1 font-lock-function-name-face) (2 font-lock-keyword-face))
167   )
168  "Basic SNMP MIB mode expression highlighting.")
169
170(defvar snmp-font-lock-keywords-2
171  (append
172   '(("ACCESS\\|BEGIN\\|DE\\(FVAL\\|SCRIPTION\\)\\|END\\|FROM\\|I\\(MPORTS\\|NDEX\\)\\|S\\(TATUS\\|YNTAX\\)"
173      (0 font-lock-keyword-face)))
174   snmp-font-lock-keywords-1)
175  "Medium SNMP MIB mode expression highlighting.")
176
177(defvar snmp-font-lock-keywords-3
178  (append
179   '(("\\([^\n]+\\)[ \t]+::=[ \t]+\\(SEQUENCE\\)[ \t]+{"
180      (1 font-lock-reference-face) (2 font-lock-keyword-face))
181     ("::=[ \t]*{[ \t]*\\([a-z0-9].*[ \t]+\\)?\\([0-9]+\\)[ \t]*}"
182      (1 font-lock-reference-face nil t) (2 font-lock-variable-name-face)))
183   snmp-font-lock-keywords-2)
184  "Gaudy SNMP MIB mode expression highlighting.")
185
186(defvar snmp-font-lock-keywords snmp-font-lock-keywords-1
187  "Default SNMP MIB mode expression highlighting.")
188
189
190;; These lists are used for the completion capabilities in the tempo
191;; templates.
192;;
193
194(defvar snmp-mode-syntax-list nil
195  "Predefined types for SYNTAX clauses.")
196
197(defvar snmp-rfc1155-types
198  '(("INTEGER") ("OCTET STRING") ("OBJECT IDENTIFIER") ("NULL") ("IpAddress")
199    ("NetworkAddress") ("Counter") ("Gauge") ("TimeTicks") ("Opaque"))
200  "Types from RFC 1155 v1 SMI.")
201
202(defvar snmp-rfc1213-types
203  '(("DisplayString"))
204  "Types from RFC 1213 MIB-II.")
205
206(defvar snmp-rfc1902-types
207  '(("INTEGER") ("OCTET STRING") ("OBJECT IDENTIFIER") ("Integer32")
208    ("IpAddress") ("Counter32") ("Gauge32") ("Unsigned32") ("TimeTicks")
209    ("Opaque") ("Counter64"))
210  "Types from RFC 1902 v2 SMI.")
211
212(defvar snmp-rfc1903-types
213  '(("DisplayString") ("PhysAddress") ("MacAddress") ("TruthValue")
214    ("TestAndIncr") ("AutonomousType") ("InstancePointer")
215    ("VariablePointer") ("RowPointer") ("RowStatus") ("TimeStamp")
216    ("TimeInterval") ("DateAndTime") ("StorageType") ("TDomain")
217    ("TAddress"))
218  "Types from RFC 1903 Textual Conventions.")
219
220
221(defvar snmp-mode-access-list nil
222  "Predefined values for ACCESS clauses.")
223
224(defvar snmp-rfc1155-access
225  '(("read-only") ("read-write") ("write-only") ("not-accessible"))
226  "ACCESS values from RFC 1155 v1 SMI.")
227
228(defvar snmp-rfc1902-access
229  '(("read-only") ("read-write") ("read-create") ("not-accessible")
230    ("accessible-for-notify"))
231  "ACCESS values from RFC 1155 v1 SMI.")
232
233
234(defvar snmp-mode-status-list nil
235  "Predefined values for STATUS clauses.")
236
237(defvar snmp-rfc1212-status
238  '(("mandatory") ("obsolete") ("deprecated"))
239  "STATUS values from RFC 1212 v1 SMI.")
240
241(defvar snmp-rfc1902-status
242  '(("current") ("obsolete") ("deprecated"))
243  "STATUS values from RFC 1902 v2 SMI.")
244
245
246;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
247;;;----------------------------------------------------------------------------
248;;
249;;                  Nothing to customize below here.
250;;
251;;;----------------------------------------------------------------------------
252;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
253
254
255;; Need this stuff when compiling for imenu macros, etc.
256;;
257(eval-when-compile
258  (require 'cl)
259  (require 'imenu))
260
261
262;; Create abbrev table for SNMP MIB mode
263;;
264(defvar snmp-mode-abbrev-table nil
265  "Abbrev table in use in SNMP mode.")
266(define-abbrev-table 'snmp-mode-abbrev-table ())
267
268
269;; Create abbrev table for SNMPv2 mode
270;;
271(defvar snmpv2-mode-abbrev-table nil
272  "Abbrev table in use in SNMPv2 mode.")
273(define-abbrev-table 'snmpv2-mode-abbrev-table ())
274
275
276;; Set up our keymap
277;;
278(defvar snmp-mode-map (make-sparse-keymap)
279  "Keymap used in SNMP mode.")
280
281(define-key snmp-mode-map "\t"           'snmp-indent-command)
282(define-key snmp-mode-map "\177"         'backward-delete-char-untabify)
283
284(define-key snmp-mode-map "\C-c\C-i"     'tempo-complete-tag)
285(define-key snmp-mode-map "\C-c\C-f"     'tempo-forward-mark)
286(define-key snmp-mode-map "\C-c\C-b"     'tempo-backward-mark)
287
288
289;; Set up our syntax table
290;;
291(defvar snmp-mode-syntax-table nil
292  "Syntax table used for buffers in SNMP mode.")
293
294(if snmp-mode-syntax-table
295    ()
296  (setq snmp-mode-syntax-table (make-syntax-table))
297  (modify-syntax-entry ?\\  "\\"     snmp-mode-syntax-table)
298  (modify-syntax-entry ?-   "_ 1234" snmp-mode-syntax-table)
299  (modify-syntax-entry ?\n  ">"      snmp-mode-syntax-table)
300  (modify-syntax-entry ?\^m ">"      snmp-mode-syntax-table)
301  (modify-syntax-entry ?_   "."      snmp-mode-syntax-table)
302  (modify-syntax-entry ?:   "."      snmp-mode-syntax-table)
303  (modify-syntax-entry ?=   "."      snmp-mode-syntax-table))
304
305;; Set up the stuff that's common between snmp-mode and snmpv2-mode
306;;
307(defun snmp-common-mode (name mode abbrev font-keywords imenu-index tempo-tags)
308  (kill-all-local-variables)
309
310  ;; Become the current major mode
311  (setq mode-name name)
312  (setq major-mode mode)
313
314  ;; Activate keymap, syntax table, and abbrev table
315  (use-local-map snmp-mode-map)
316  (set-syntax-table snmp-mode-syntax-table)
317  (setq local-abbrev-table abbrev)
318
319  ;; Set up paragraphs (?)
320  (make-local-variable 'paragraph-start)
321  (setq paragraph-start (concat "$\\|" page-delimiter))
322  (make-local-variable 'paragraph-separate)
323  (setq paragraph-separate paragraph-start)
324  (make-local-variable 'paragraph-ignore-fill-prefix)
325  (setq paragraph-ignore-fill-prefix t)
326
327  ;; Set up comments
328  (make-local-variable 'comment-start)
329  (setq comment-start "-- ")
330  (make-local-variable 'comment-start-skip)
331  (setq comment-start-skip "--+[ \t]*")
332  (make-local-variable 'comment-column)
333  (setq comment-column 40)
334  (make-local-variable 'parse-sexp-ignore-comments)
335  (setq parse-sexp-ignore-comments t)
336
337  ;; Set up indentation
338  (make-local-variable 'indent-line-function)
339  (setq indent-line-function (if snmp-special-indent
340                                 'snmp-indent-line
341                               'indent-to-left-margin))
342
343  ;; Font Lock
344  (make-local-variable 'font-lock-defaults)
345  (setq font-lock-defaults (cons font-keywords '(nil nil ((?- . "w 1234")))))
346
347  ;; Imenu
348  (make-local-variable 'imenu-create-index-function)
349  (setq imenu-create-index-function imenu-index)
350
351  ;; Tempo
352  (tempo-use-tag-list tempo-tags)
353  (make-local-variable 'tempo-match-finder)
354  (setq tempo-match-finder "\\b\\(.+\\)\\=")
355  (make-local-variable 'tempo-interactive)
356  (setq tempo-interactive t)
357
358  ;; Miscellaneous customization
359  (make-local-variable 'require-final-newline)
360  (setq require-final-newline mode-require-final-newline))
361
362
363;; SNMPv1 MIB Editing Mode.
364;;
365;;;###autoload
366(defun snmp-mode ()
367  "Major mode for editing SNMP MIBs.
368Expression and list commands understand all C brackets.
369Tab indents for C code.
370Comments start with -- and end with newline or another --.
371Delete converts tabs to spaces as it moves back.
372\\{snmp-mode-map}
373Turning on snmp-mode runs the hooks in `snmp-common-mode-hook', then
374`snmp-mode-hook'."
375  (interactive)
376
377  (snmp-common-mode "SNMP" 'snmp-mode
378                   snmp-mode-abbrev-table
379                   '(snmp-font-lock-keywords
380                     snmp-font-lock-keywords-1
381                     snmp-font-lock-keywords-2
382                     snmp-font-lock-keywords-3)
383                   'snmp-mode-imenu-create-index
384                   'snmp-tempo-tags)
385
386  ;; Completion lists
387  (make-local-variable 'snmp-mode-syntax-list)
388  (setq snmp-mode-syntax-list (append snmp-rfc1155-types
389                                     snmp-rfc1213-types
390                                     snmp-mode-syntax-list))
391  (make-local-variable 'snmp-mode-access-list)
392  (setq snmp-mode-access-list snmp-rfc1155-access)
393  (make-local-variable 'snmp-mode-status-list)
394  (setq snmp-mode-status-list snmp-rfc1212-status)
395
396  ;; Run hooks
397  (run-mode-hooks 'snmp-common-mode-hook 'snmp-mode-hook))
398
399
400;;;###autoload
401(defun snmpv2-mode ()
402  "Major mode for editing SNMPv2 MIBs.
403Expression and list commands understand all C brackets.
404Tab indents for C code.
405Comments start with -- and end with newline or another --.
406Delete converts tabs to spaces as it moves back.
407\\{snmp-mode-map}
408Turning on snmp-mode runs the hooks in `snmp-common-mode-hook',
409then `snmpv2-mode-hook'."
410  (interactive)
411
412  (snmp-common-mode "SNMPv2" 'snmpv2-mode
413                   snmpv2-mode-abbrev-table
414                   '(snmp-font-lock-keywords
415                     snmp-font-lock-keywords-1
416                     snmp-font-lock-keywords-2
417                     snmp-font-lock-keywords-3)
418                   'snmp-mode-imenu-create-index
419                   'snmpv2-tempo-tags)
420
421  ;; Completion lists
422  (make-local-variable 'snmp-mode-syntax-list)
423  (setq snmp-mode-syntax-list (append snmp-rfc1902-types
424                                     snmp-rfc1903-types
425                                     snmp-mode-syntax-list))
426  (make-local-variable 'snmp-mode-access-list)
427  (setq snmp-mode-access-list snmp-rfc1902-access)
428  (make-local-variable 'snmp-mode-status-list)
429  (setq snmp-mode-status-list snmp-rfc1902-status)
430
431  ;; Run hooks
432  (run-mode-hooks 'snmp-common-mode-hook 'snmpv2-mode-hook))
433
434
435;;;----------------------------------------------------------------------------
436;;
437;;                           Indentation Setup
438;;
439;;;----------------------------------------------------------------------------
440
441(defvar snmp-macro-open
442  "[a-zA-Z][-a-zA-Z0-9]*[ \t]*\\(OBJECT\\|TRAP\\)-\\(TYPE\\|GROUP\\)\
443\\|DESCRIPTION\\|IMPORTS\\|MODULE\\(-IDENTITY\\|-COMPLIANCE\\)\
444\\|.*::=[ \t]*\\(BEGIN\\|TEXTUAL-CONVENTION\\)[ \t]*$")
445
446(defvar snmp-macro-close
447  "::=[ \t]*{\\|\\(END\\|.*[;\"]\\)[ \t]*$")
448
449(defun snmp-calculate-indent ()
450  "Calculate the current line indentation in SNMP MIB code.
451
452We use a very simple scheme: if the previous non-empty line was a \"macro
453open\" string, add `snmp-indent-level' to it.  If it was a \"macro close\"
454string, subtract `snmp-indent-level'.  Otherwise, use the same indentation
455as the previous non-empty line.  Note comments are considered empty
456lines for the purposes of this function."
457  (let ((empty (concat "\\([ \t]*\\)\\(" comment-start-skip "\\|$\\)"))
458        (case-fold-search nil)) ; keywords must be in uppercase
459    (save-excursion
460      (while (and (>= (forward-line -1) 0)
461                  (looking-at empty)))
462      (skip-chars-forward " \t")
463      (+ (current-column)
464         ;; Are we looking at a macro open string?  If so, add more.
465         (cond ((looking-at snmp-macro-open)
466                snmp-indent-level)
467               ;; macro close string?  If so, remove some.
468               ((looking-at snmp-macro-close)
469                (- snmp-indent-level))
470               ;; Neither; just stay here.
471               (t 0))))))
472
473(defun snmp-indent-line ()
474  "Indent current line as SNMP MIB code."
475  (let ((indent (snmp-calculate-indent))
476        (pos (- (point-max) (point)))
477        shift-amt beg end)
478    (beginning-of-line)
479    (setq beg (point))
480    (skip-chars-forward " \t")
481    (setq shift-amt (- indent (current-column)))
482    (if (zerop shift-amt)
483        nil
484      (delete-region beg (point))
485      (indent-to indent))
486    ;; If initial point was within line's indentation,
487    ;; position after the indentation.  Else stay at same point in text.
488    (if (> (- (point-max) pos) (point))
489        (goto-char (- (point-max) pos)))))
490
491(defun snmp-indent-command ()
492  "Indent current line as SNMP MIB code, or sometimes insert a TAB.
493If `snmp-tab-always-indent' is t, always reindent the current line when
494this command is run.
495If `snmp-tab-always-indent' is nil, reindent the current line if point is
496in the initial indentation.  Otherwise, insert a TAB."
497  (interactive)
498  (if (and (not snmp-tab-always-indent)
499           (save-excursion
500             (skip-chars-backward " \t")
501             (not (bolp))))
502      (insert-tab)
503    (snmp-indent-line)))
504
505
506;;;----------------------------------------------------------------------------
507;;
508;;                              Imenu Setup
509;;
510;;;----------------------------------------------------------------------------
511
512(defvar snmp-clause-regexp
513  "^[ \t]*\\([a-zA-Z][-a-zA-Z0-9]*\\)[ \t\n]*\
514\\(TRAP-TYPE\\|::=\\|OBJECT\\(-TYPE[ \t\n]+SYNTAX\\|[ \t\n]+IDENTIFIER[ \t\n]*::=\\)\\)")
515
516(defun snmp-mode-imenu-create-index ()
517  (let ((index-alist '())
518	(index-oid-alist '())
519	(index-tc-alist '())
520	(index-table-alist '())
521	(index-trap-alist '())
522        (case-fold-search nil) ; keywords must be uppercase
523	prev-pos token marker end)
524    (goto-char (point-min))
525    (imenu-progress-message prev-pos 0)
526    ;; Search for a useful MIB item (that's not in a comment)
527    (save-match-data
528      (while (re-search-forward snmp-clause-regexp nil t)
529        (imenu-progress-message prev-pos)
530        (setq
531         end (match-end 0)
532         token (cons (buffer-substring (match-beginning 1) (match-end 1))
533                     (set-marker (make-marker) (match-beginning 1))))
534        (goto-char (match-beginning 2))
535        (cond ((looking-at "OBJECT-TYPE[ \t\n]+SYNTAX")
536               (push token index-alist))
537              ((looking-at "OBJECT[ \t\n]+IDENTIFIER[ \t\n]*::=")
538               (push token index-oid-alist))
539              ((looking-at "::=[ \t\n]*SEQUENCE[ \t\n]*{")
540               (push token index-table-alist))
541              ((looking-at "TRAP-TYPE")
542               (push token index-trap-alist))
543              ((looking-at "::=")
544               (push token index-tc-alist)))
545        (goto-char end)))
546    ;; Create the menu
547    (imenu-progress-message prev-pos 100)
548    (setq index-alist (nreverse index-alist))
549    (and index-tc-alist
550 	 (push (cons "Textual Conventions" (nreverse index-tc-alist))
551  	       index-alist))
552    (and index-trap-alist
553	 (push (cons "Traps" (nreverse index-trap-alist))
554               index-alist))
555    (and index-table-alist
556 	 (push (cons "Tables" (nreverse index-table-alist))
557  	       index-alist))
558    (and index-oid-alist
559 	 (push (cons "Object IDs" (nreverse index-oid-alist))
560  	       index-alist))
561    index-alist))
562
563
564;;;----------------------------------------------------------------------------
565;;
566;;                              Tempo Setup
567;;
568;;;----------------------------------------------------------------------------
569
570(require 'tempo)
571
572;; Perform a completing-read with info given
573;;
574(defun snmp-completing-read (prompt table &optional pred require init hist)
575  "Read from the minibuffer, with completion.
576Like `completing-read', but the variable `snmp-completion-ignore-case'
577controls whether case is significant."
578  (let ((completion-ignore-case snmp-completion-ignore-case))
579    (completing-read prompt table pred require init hist)))
580
581;; OBJECT-TYPE macro template
582;;
583(tempo-define-template "snmp-object-type"
584  '(> (P "Object Label: ") " OBJECT-TYPE" n>
585    "SYNTAX  "
586    (if tempo-interactive
587        (snmp-completing-read "Syntax: " snmp-mode-syntax-list nil nil)
588      p) n>
589    "ACCESS  "
590    (if tempo-interactive
591        (snmp-completing-read "Access: " snmp-mode-access-list nil t)
592      p) n>
593    "STATUS  "
594    (if tempo-interactive
595        (snmp-completing-read "Status: " snmp-mode-status-list nil t)
596      p) n>
597    "DESCRIPTION" n> "\"" p "\"" n>
598    (P "Default Value: " defval t)
599    (if (string= "" (tempo-lookup-named 'defval))
600        nil
601      '(l "DEFVAL { " (s defval) " }" n>))
602    "::= { " (p "OID: ") " }" n)
603  "objectType"
604  "Insert an OBJECT-TYPE macro."
605  'snmp-tempo-tags)
606
607;; Table macro template
608;;
609(tempo-define-template "snmp-table-type"
610  ;; First the table OBJECT-TYPE
611  '(> (P "Table Name: " table)
612    (P "Entry Name: " entry t)
613    (let* ((entry (tempo-lookup-named 'entry))
614           (seq (copy-sequence entry)))
615      (aset entry 0 (downcase (aref entry 0)))
616      (aset seq 0 (upcase (aref seq 0)))
617      (tempo-save-named 'obj-entry entry)
618      (tempo-save-named 'seq-entry seq)
619      nil)
620    " OBJECT-TYPE" n>
621    "SYNTAX  SEQUENCE OF "
622    (s seq-entry) n>
623    "ACCESS  not-accessible" n>
624    "STATUS  mandatory" n>
625    "DESCRIPTION" n> "\"" p "\"" n>
626    "::= { " (p "OID: ") " }" n n>
627   ;; Next the row OBJECT-TYPE
628    (s obj-entry) " OBJECT-TYPE" n>
629    "SYNTAX  " (s seq-entry) n>
630    "ACCESS  not-accessible" n>
631    "STATUS  mandatory" n>
632    "DESCRIPTION" n> "\"" p "\"" n>
633    "INDEX   { " (p "Index List: ") " }" n>
634    "::= {" (s table) " 1 }" n n>
635   ;; Finally the SEQUENCE type
636    (s seq-entry) " ::= SEQUENCE {" n> p n> "}" n)
637  "tableType"
638  "Insert an SNMP table."
639  'snmp-tempo-tags)
640
641
642;; v2 SMI OBJECT-TYPE macro template
643;;
644(tempo-define-template "snmpv2-object-type"
645  '(> (P "Object Label: ") " OBJECT-TYPE" n>
646    "SYNTAX      "
647    (if tempo-interactive
648        (snmp-completing-read "Syntax: " snmp-mode-syntax-list nil nil)
649      p) n>
650    "MAX-ACCESS  "
651    (if tempo-interactive
652        (snmp-completing-read "Max Access: " snmp-mode-access-list nil t)
653      p) n>
654    "STATUS      "
655    (if tempo-interactive
656        (snmp-completing-read "Status: " snmp-mode-status-list nil t)
657      p) n>
658    "DESCRIPTION" n> "\"" p "\"" n>
659    (P "Default Value: " defval t)
660    (if (string= "" (tempo-lookup-named 'defval))
661        nil
662      '(l "DEFVAL { " (s defval) " }" n>))
663    "::= { " (p "OID: ") " }" n)
664  "objectType"
665  "Insert an v2 SMI OBJECT-TYPE macro."
666  'snmpv2-tempo-tags)
667
668;; v2 SMI Table macro template
669;;
670(tempo-define-template "snmpv2-table-type"
671  ;; First the table OBJECT-TYPE
672  '(> (P "Table Name: " table)
673    (P "Entry Name: " entry t)
674    (let* ((entry (tempo-lookup-named 'entry))
675           (seq (copy-sequence entry)))
676      (aset entry 0 (downcase (aref entry 0)))
677      (aset seq 0 (upcase (aref seq 0)))
678      (tempo-save-named 'obj-entry entry)
679      (tempo-save-named 'seq-entry seq)
680      nil)
681    " OBJECT-TYPE" n>
682    "SYNTAX      SEQUENCE OF "
683    (s seq-entry) n>
684    "MAX-ACCESS  not-accessible" n>
685    "STATUS      current" n>
686    "DESCRIPTION" n> "\"" p "\"" n>
687    "::= { " (p "OID: ") " }" n n>
688   ;; Next the row OBJECT-TYPE
689    (s obj-entry) " OBJECT-TYPE" n>
690    "SYNTAX      " (s seq-entry) n>
691    "MAX-ACCESS  not-accessible" n>
692    "STATUS      current" n>
693    "DESCRIPTION" n> "\"" p "\"" n>
694    "INDEX { " (p "Index List: ") " }" n>
695    "::= { " (s table) " 1 }" n n>
696   ;; Finally the SEQUENCE type
697    (s seq-entry) " ::= SEQUENCE {" n> p n> "}" n)
698  "tableType"
699  "Insert an v2 SMI SNMP table."
700  'snmpv2-tempo-tags)
701
702;; v2 SMI TEXTUAL-CONVENTION macro template
703;;
704(tempo-define-template "snmpv2-textual-convention"
705  '(> (P "Texual Convention Type: ") " ::= TEXTUAL-CONVENTION" n>
706    "STATUS  "
707    (if tempo-interactive
708        (snmp-completing-read "Status: " snmp-mode-status-list nil t)
709      p) n>
710    "DESCRIPTION" n> "\"" p "\"" n>
711    "SYNTAX  "
712    (if tempo-interactive
713        (snmp-completing-read "Syntax: " snmp-mode-syntax-list nil nil)
714      p) n> )
715  "textualConvention"
716  "Insert an v2 SMI TEXTUAL-CONVENTION macro."
717  'snmpv2-tempo-tags)
718
719
720(provide 'snmp-mode)
721
722;;; arch-tag: eb6cc0f9-1e47-4023-8625-bc9aae6c3527
723;;; snmp-mode.el ends here
724