-
Notifications
You must be signed in to change notification settings - Fork 37
/
cligen_tutorial.tex
1658 lines (1368 loc) · 52.7 KB
/
cligen_tutorial.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\documentclass[a4paper, 10pt] {article}
\usepackage{graphicx}
\usepackage{fancyhdr}
\usepackage[parfill]{}
\pagestyle{fancyplain}
%
% Title
%
\title {CLIgen Manual\\ {\small CLIgen version 7.0}}
\author{Olof Hagsand}
%
% Go!
%
\begin{document}
% If you want a logo
% \lhead{\includegraphics[height=9mm]{../../doc/logga_crop.png}}
\date{May, 2024}
\maketitle
\setcounter{tocdepth}{2}
\tableofcontents
\newpage
\section{Introduction}
\label{sec:intro}
CLIgen builds interactive syntax-driven \emph{command-line interfaces}
in C from a high-level syntax specification. Interactive CLIs are
often used in communication devices such as routers and
switches. However, any devices with a textual, syntax-driven,
command-based interface can use CLIgen to make CLI programming easy.
CLIgen takes a syntax specification as input, generates a tree
representation of the syntax, and provides an interactive command-line
tool with completion, help, modes, etc.
A designer formulates the command-line syntax and writes callback
functions in C to implement the semantics of the commands.
A good starting point is the hello world example with a simple syntax
specification ("hello world") and a callback with a print statement,
which produces the following CLI executable:
\begin{verbatim}
> ./cligen_hello
hello> hello world
Hello World!
hello>
\end{verbatim}
The complete {\tt cligen\_hello} C application is included in the
source code distribution.
\begin{figure}
\centering
\includegraphics[scale=0.8]{usage.pdf}
\caption{\em CLIgen usage: a designer implements a CLI by specificying the syntax in a specification file and the CLI source code using the CLIgen API.}
\label{fig:usage}
\end{figure}
Figure~\ref{fig:usage} shows a typical workflow when working with
CLIgen. A designer specifies the CLI syntax by editing a CLIgen
specification file and writing a C-program. When users access the CLI
at runtime, the specification file is loaded and the CLI uses the API
of the CLIgen library to interpret the commands.
An example of a CLIgen specification file of the hello world application is:
\begin{verbatim}
prompt="hello> " # Assignment of prompt
hello("Greet the world"){ # 'hello' command with help text
world, cb("Hello World!"); # 'world' command with callback
}
\end{verbatim}
The specification above shows examples of the following key ingredients of a specification:
\begin{itemize}
\item
\emph{Command syntax} specifies the syntax of the actual commands, and
are the main part of a specification. The command syntax is fully
described in Section~\ref{sec:syntax}.
\item
\emph{Callbacks} are functions called when a command has been entered
by a user. You may specify an argument to a callback. Callbacks
are a part of the API described in Section~\ref{sec:api}.
\item
\emph{Assignments} are used to set properties of the CLI and its
commands, such as prompts, visibility, etc. Assignments are either global or per-command.
\item
\emph{Help text} provides help text for individual commands.
\item
\emph{Comments} begin with the '\#' sign, at start of a line or at the beginning of a word.
\end{itemize}
The following sections will describe all aspects of designing CLIgen
application. Programming using the CLIgen API in C is described in
Section~\ref{sec:api}.
\section{Command syntax}
\label{sec:syntax}
The command syntax consists of a combination of keywords, variables and
operators:
\begin{itemize}
\item
\emph{Keywords} are constant strings representing fixed command words.
\item
\emph{Variables} are placeholders for user-defined input.
\item
\emph{Operators} are used to combine keywords and variables in different ways. Operators
include 'choice', 'option', 'sequence', etc. Operators are further described in Section~\ref{sec:operators}.
\end{itemize}
For example, the command syntax {\tt ip tcp <uint16>;} have two keywords:
{\tt ip}, and {\tt tcp} and one variable: {\tt <uint16>}. They are
combined in a \emph{sequence}, that is, the CLI expects them to be
typed one after the other.
\subsection{Keywords}
The simplest syntax consists only of keywords. Such a syntax can be
specified as follows:
\begin{verbatim}
aa bb{
ca;
cb;{
dd;
ee;
}
}
ff;
\end{verbatim}
A CLI loaded with the specification above accepts the following strings as input:
\begin{verbatim}
aa bb ca
aa bb cb
aa bb cb dd
aa bb cb ee
ff
\end{verbatim}
Note the following:
\begin{itemize}
\item Newlines are not significant, except after comments. This means
that another way of specifying the syntax above is: {\tt aa
bb\{ca;cb;\{dd;ee;\}\}ff;}.
\item Keywords specified one after another is a
sequence. Example: {\tt aa bb;}. An alternative of expressing the same syntax is: {\tt aa\{bb;\}}
\item Semicolon terminates a complete command. This means that {\tt aa bb cb}
is accepted as a complete command, but not {\tt aa bb} in the syntax above.
\item Semicolons also act as a choice, you can choose either {\tt dd}
or {\tt ee} in the syntax above.
\item Keywords can also be specified using variables: {\tt
<string keyword:aa>}, there are some advantages with this which may
get apparent when programming using the API (see
Section~\ref{sec:api}).
\item The syntax above can be written in a more compact way, such as {\tt aa bb (ca|cb [dd|ee]);ff;}. This is described more in Section~\ref{sec:operators}
\end{itemize}
\subsection{Runtime behaviour}
A CLI with the syntax above will present the user with a list of
commands. On the top-level, only {\tt aa} or {\tt bb} may be chosen when a question mark is entered:
\begin{verbatim}
> '?'
aa
gg
\end{verbatim}
If the user prints an 'a', followed by a 'TAB', the CLI performs
completion to {\tt aa} since there is only one alternative:
\begin{verbatim}
> a'TAB'
> aa 'TAB'
> aa bb 'TAB'
> aa bb c'TAB'
ca cb
> aa bb c
\end{verbatim}
In the example, two more {\tt TAB}s are entered, one for each command
level and completion continues until the commands are not unique. In
the last {\tt TAB}, the CLI shows the available commands ({\tt ca} and {\tt cb}).
As long as a command is unique it is not necessary to
complete the whole string. For example, the following two strings are
equivalent from the CLIs perspective:
\begin{verbatim}
> aa bb cb dd
> a b cb d
\end{verbatim}
Before finishing a command (with return), a unique
command must be selected. The CLI gives an error code if the command
is unknown, ambiguous or incomplete:
\begin{verbatim}
> a
CLI syntax error in: "a": Incomplete command
> aa bb c
CLI syntax error in: "aa bb c": Ambiguous command
> aa bb dd
CLI syntax error in: "aa bb dd": Unknown command
\end{verbatim}
\subsection{Escaping}
In the CLIgen runtime, some characters have special meaning, such as
{\tt '?'}. You can \emph{escape} characters with backslash({\tt '\textbackslash'}) so
that for example {\tt '?'} can appear in a keyword or value:
\begin{verbatim}
> a\?b # Gives the string "a?b"
> a\\b # Gives the string "a\b"
\end{verbatim}
\subsection{Help texts}
Help texts are given within parenthesis following a keyword or
variable. The help text appears when you invoke the help command '?'
in the CLI runtime.
For example, assume the following syntax:
\begin{verbatim}
ip("The IP protocol"){
udp("The UDP protocol") <ipaddr>("IPv4 address");
tcp("The TCP protocol") <uint16>("Port number");
}
\end{verbatim}
If a user has typed 'ip ' and '?', the following help text appears:
\begin{verbatim}
cli> ip '?'
tcp The TCP protocol
udp The UDP protocol
\end{verbatim}
\subsection{Callbacks}
\label{sec:callbacks}
When a unique command has been selected, a callback may be
called. Callbacks are typically associated with commands using the
file syntax:
\begin{verbatim}
aa bb{
ca,fn1("ca");
cb,fn1("cb");{
dd,fn2();
ee,fn3((int)42);
}
}
\end{verbatim}
In the example, the function {\tt fn1} is called with {\tt "ca"} as
argument if {\tt aa bb ca}, is selected. The same function is called
also if {\tt aa bb cb} is selected, but with another argument. For
other commands, {\tt fn2} is called without argument, and {\tt fn3} is
called with the integer argument {\tt 42}.
Note that callbacks may only be associated with terminal commands. For
example, {\tt aa bb} may not have a callback function.
The details on how to write callback functions, such as {\tt fn1} -
{\tt fn3} is described in detail in Section~\ref{sec:api}.
\subsection{Assignments}
\label{sec:assignments}
You can assign values to \emph{global} and \emph{local}
variables. Global variables are valid for the whole syntax, while
local variables only apply to a single command.
In the current release, there are three pre-defined local variables:
\begin{itemize}
\item
{\tt hide} : specifies that a command is not visible in auto completion, meaning when listing or completing commands with '?' and 'TAB'. This can be useful if there are commands that should be known only by expert users.
\end{itemize}
In the following example, {\tt aa bb cb dd} and {\tt aa bb cc} are not visible in database and/or auto completion
depending on the variable used as mentioned above :
\begin{verbatim}
aa bb{
ca;
cb, hide{
dd;
}
cc, hide;
}
\end{verbatim}
A {\em global} variable is assigned on the top-level. There is
currently only one pre-defined global variable ({\tt treename} as
described in the next section). But it is easy for a programmer to
implement a global variable and define semantics to it.
The tutorial application supports prompt and comment character:
\begin{verbatim}
prompt="cli> "; # Assignment of prompt
comment="#"; # Same comment as in syntax
\end{verbatim}
Section~\ref{sec:global} describes how the C-API can be used to define
semantics for a global variable.
\subsection{Trees}
CLIgen can handle multiple syntax trees. A user can switch between
trees (i.e., change CLI mode), or extend a tree with a sub-tree (using
tree-references).
A tree is named using a special global {\tt treename} assignment. The
following example shows two syntax trees: {\tt tree1} and {\tt tree2}.
\begin{verbatim}
treename="tree1";
x{
y;
}
treename="tree2";
z{
x;
}
\end{verbatim}
When parsing the syntax above, a CLIgen tree-list consisting of two
trees will be created. By default, the first parsed tree is the active tree.
\begin{verbatim}
changetree <tree:string>, changetree("tree2");
\end{verbatim}
Note that the {\tt changetree} callback needs to be implemented as a
callback function in C to actually change the syntax mode. Such a
callback is implemented in the tutorial and is also described in more
detail in Section~\ref{sec:api}.
Note, the {\tt treename} feature is not available in Clixon, only in stand-alone CLIgen.
\subsubsection{Tree references}
A CLIgen syntax tree may reference another tree as an extension using
the reference operator {\tt @}.
The following specification references itself:
\begin{verbatim}
treename="T";
foo;
recurse @T;
\end{verbatim}
which means that the following sentences are valid commands:
\begin{verbatim}
foo
recurse foo
recurse recurse foo
recurse recurse recurse foo
\end{verbatim}
and so on.
Callbacks can be parametrized when using tree references. This means
that you can specify which callback to use in the reference of the
tree. This means that different callbacks can be called depending on
how you reference the tree.
The following examples shows a main tree and a sub-tree.
\begin{verbatim}
treename="main";
add @sub, addfn();
del @sub, delfn();
treename="sub";
x{
y, fn("a1");
}
\end{verbatim}
The main tree references the subtree twice. In the first reference,
{\tt addfn("a1")} is called when invoking the command {\tt add x y}. In the
second instance {\tt delfn("a")} is invoked when invoking the command {\tt del x y}.
It may be useful with functional substitution as shown above when the
subtree represents a large common data-modeling sub-tree, where the
data (x y) is the same but the operation(add/del) is different.
\subsubsection{Tree reference callback parameters}
In the example above, the tree reference have no parameters ({\tt add();} and the local parameter. If instead the reference
does have some parameters a special parameter appending mechanism is used.
Assume the following tree spec:
\begin{verbatim}
treename="main";
add @sub, addfn("x1","x2");
treename="sub";
x{
y, fn("a1","a2");
}
\end{verbatim}
The {\tt addfn()} callback is the called with the local parameters first, then the ones in the reference.
In other words, if the user types {\tt add x y}, then the following function call is made: {\tt addfn("a1", "a2", "x1", "x2")}. You need to ensure that {\tt addfn()} can handle these arguments.
The reason for this mechanism is the autocli in Clixon, where it is used to generate a CLI from a YANG specification.
\subsubsection{Filtering trees}
When referencing a tree with the {\tt @tree} syntax, it is possible to filter the tree by removing
objects with specific labels. This can be useful if multiple references to a tree is made, but
the instanciations differ.
For example, assume the following subtree ``T'', where one leaf is labelled with flag ``local'':
\begin{verbatim}
x {
y, local;
z;
}
\end{verbatim}
Then this tree can be referenced as: {\tt @T, @remove:local;} in which case the expanded tree has removed all tree nodes labelled with ``local'' as follows:
\begin{verbatim}
x {
z;
}
\end{verbatim}
\subsubsection{Direct sub-expansion}
If a treeref statement is placed directly on the top level of the
expanded tree, it will also be expanded.
\begin{verbatim}
treename="main";
add @sub;
treename="sub";
@extra
x;
treename="extra";
y;
\end{verbatim}
which means that both {\tt add x} and {\tt add y} are valid statements.
\subsubsection{Tree workpoints}
When using tree references it is possible to set an active {\em
workpoint} for that tree, which can change dynamically. In this way,
a user can navigate up and down the tree in its references for it. This
is useful when implementing automatic modes for example.
To achieve this, a couple of C-API callbacks are available:
\begin{itemize}
\item {\tt cligen\_wp\_set(<tree>)} - Set the workpoint
\item {\tt cligen\_wp\_show(<tree>)} - Show the tree at the active workpoint
\item {\tt cligen\_wp\_up(<tree>)} - Navigate up in the tree
\item {\tt cligen\_wp\_top(<tree>)} - Navigate to top of tree
\end{itemize}
Assume first a tree ``T'' is created that will be navigated in using workpoints:
\begin{verbatim}
treename="T";
a; {
b <v:int32>; {
d;
}
c;
}
\end{verbatim}
Then, some main syntax for navigating in three is added in the main CLIgen spec:
\begin{verbatim}
edit, cligen_wp_set("T");{
@T, cligen_wp_set("T");
}
show, cligen_wp_show("T");
up, cligen_wp_up("T");
top, cligen_wp_top("T");
\end{verbatim}
It is now possible to traverse the tree using the ``T'' tree as the following example illustrates (the prompt shows the location of the active workpoint):
\begin{verbatim}
cli:/> show
a;{
b <v>;{
d;
}
c;
}
cli:/> edit a
cli:/a> show
b <v>;{
d;
}
c;
cli:/a> edit b 23
cli:/a/b/23> show
d;
cli:/a/b/23> up
cli:/a/b> show
<v>;{
d;
}
cli> top
cli:/> show
a;{
b <v>;{
d;
}
c;
}
cli:/>
\end{verbatim}
\subsection{Output pipes}
\label{sec:pipes}
Output pipes resemble UNIX shell pipes and are useful to filter or modify CLI output. Example:
\begin{verbatim}
cli> print all | grep parameter
<parameter>5</parameter>
<parameter>x</parameter>
cli>
\end{verbatim}
Output pipe functions are declared using a special variant of a tree
with a name starting with vertical bar. Example:
\begin{verbatim}
treename="|mypipe";
\| {
grep <arg:rest>, grep_fn("grep -e", "arg");
tail, tail_fn();
}
\end{verbatim}
where {\tt grep\_fn} and {\tt tail\_fn} are special callbacks that use stdio to modify output.
Such a pipe tree can be referenced with either an explicit reference, or an implicit rule.
An explicit reference looks something like this:
\begin{verbatim}
print {
all, @|mypipe, print_cb("all");
detail, @|mypipe, print_cb("detail");
}
\end{verbatim}
where a pipe tree is added as a tree reference, appending pipe functions to the regular {\tt print\_cb} callback.
An example of an implicit rule is as follows:
\begin{verbatim}
pipetree="|mypipe";
print {
all, print_cb("all");
detail, print_cb("detail);
}
\end{verbatim}
where the pipe tree is added implicitly to all commands.
Pipe trees also work for sub-trees, ie a subtree referenced by the top-level tree may also use output pipes.
\subsection{Sets}
\label{sec:sets}
By default, listing several commands within {\tt \{\}} gives a choice of commands, but if instead commands are within the set operator {\tt @\{\}}, the commands can be given on any order, and at least once. For example:
\begin{verbatim}
x @{
a;
b;
c;
}
\end{verbatim}
gives exactly the following allowed CLI commands, and no others:
\begin{verbatim}
x a
x a b
x a b c
x a c
x a c b
x b
x b a
x b a c
x b c
x b c a
x c
x c a
x c a b
x c b
x c b a
\end{verbatim}
\section{Variables}
\label{sec:variables}
Variables are placeholders for user input. They also give support for
lexical checking. The {\tt int32} type, for example, only
accepts 32-bit integers, while {\tt string} accepts any sequence of
characters.
\subsection{Basic structure}
A variable has the following basic components:
\begin{itemize}
\item {\em name} - How the variable is referenced, such as in a callback.
\item {\em type} - The type of the variable. If no type is given, it is by default the same as {\em name}.
\item {\em show} - How the variable is displayed in help texts (such as after a '?' or 'TAB'. If no show field is given, it defaults to {\em name}.
\end{itemize}
The variable syntax has several forms:
\begin{verbatim}
<int32>;
<a:int32>;
<a:int32 show:"a number">("A 32-bit number")
\end{verbatim}
In the first form, both name, type and show is {\tt int32}. In the
second form, the name and show is "a", while type is {\tt int32}.
In the last form, all fields are explicitly given, and there is also a help-text.
An example of the last, most explicit form in a CLI:
\begin{verbatim}
cli> '?'
<a number> A 32-bit number
\end{verbatim}
\subsection{String}
The simplest form of a string specification is: {\tt
<string>}, which defines a string variable with the name 'string'.
A more advanced string variable specification is the following:
\begin{verbatim}
address <addr:string>("Address to home");
\end{verbatim}
where the name of the string variable is {\tt addr}. The name can be used when referring to the variable in a callback, and is also used in the help text:
\begin{verbatim}
cli> address '?'
addr Address to home
\end{verbatim}
A string may contain all characters with some minor exceptions. Most
notably, a string can not contain a question mark, since it is used
for querying syntax in the CLI. Also, if a string contains spaces, it
must be contained within double quotes. The following examples are all valid
strings:
\begin{verbatim}
i_am_a_string
()/&#
"I am a string"
ab"d
\end{verbatim}
A string can be constrained by a {\tt length} statement. If given, the number of characters in a string is limited to a min/max interval, or just a max\footnote{Note that this differs from YANG types where a single bound means exactly that value, see RFC 7950}.
Example:
\begin{verbatim}
<addr:string length[8:12]>
<addr:string length[12]>
<addr:string length[2:4] length[8:12]>
\end{verbatim}
which means that the {\tt addr} string, if given, must be between 8 and 12 characters long, or just limited to 12 characters, or be between 2-4 and 8-12 charcters respectively.
\subsubsection{Rest}
A variant of string is {\tt rest} which accepts all characters until end-of-line, regardless of white space. This is useful for variable argument input.
Example of the difference between {\tt string} and {\tt rest} type:
\begin{verbatim}
single("System command") <command:string>;
command("System command") <command:rest>;
\end{verbatim}
Note the difference where the {\tt string} type accepts a single string, whereas the {\tt rest} type groups all remaining characters into a single string regardless of whitespace:
\begin{verbatim}
cli> single one two three
CLI syntax error: "single one two three": Unknown command
cli> single "one two three"
cli> command one two three
cli>
\end{verbatim}
\subsection{Integers}
There are several integer variables, signed, unsigned, and 8, 16, 32 or 64-bits. For example, the {\tt int32} variable allows any 32-bit integer, and can be specified in decimal or hex format.
Further, an allowed range of integer can specified, either as an interval or as an upper limit, or a set of ranges:
Examples:
\begin{verbatim}
<x:uint32>
<x:int8 range[-12:80] range[100:110]>>
<x:int64 range[1000]>
\end{verbatim}
\subsection{Addresses}
CLIgen is often used in communication devices. Therefore, there is
support for several pre-defined address types. Special lexical
checking is defined for those types:
\begin{itemize}
\item {\tt ipv4addr} - An IPv4 address in dotted decimal notation. Example: {\tt 1.2.3.4}
\item {\tt ipv4prefix} - An IPv4 prefix in 'slash' notation: Example: {\tt 1.2.3.0/24}
\item {\tt ipv6addr} - An IPv6 address. Example: {\tt 2001::56}
\item {\tt ipv6prefix} - An IPv6 prefix. Example: {\tt 2001:647::/64}
\item {\tt macaddr} - A MAC address: Example: {\tt 00:E0:81:B4:40:7A}
\item {\tt url} - An URL: Example: {\tt http://www.hagsand.se/cligen}
\end{itemize}
CLIgen performs lexical checking of the address variables, an invalid
address is considered as a syntax error.
\subsection{Uuid}
A variable of type {\tt uuid} accepts uuid according to standard syntax,
such as {\tt f47ac10b-58cc-4372-a567-0e02b2c3d479}.
\subsection{Time}
A {\tt time} variable accepts ISO timestamps on the form
\begin{verbatim}
2008-09-21T18:57:21.003456
2008-09-21 18:57:21.003456
2008-09-21 18:57:21
\end{verbatim}
\subsection{Boolean}
A variable of {\tt bool} type accepts the values {\tt true}, {\tt
false}, {\tt on} and {\tt off}.
\subsection{Decimal64}
A variable of type {\tt decimal64} defines a subset of floating point
numbers that can be obtained by multiplying a 64-bit signed integer
with a negative power of ten, ie as can be expressed by $i * 10^{-n}$,
where $n$ is between 1 and 18.
The number of fraction-digits can be defined in the specification of
the type, if this is not defined explicitly, the default number of decimals is 2.
Two examples of decimal64 are {\tt 732848324.2367} (four
fraction-digits) and -23.0 (one fraction-digit).
Examples of decimal64 specification is:
\begin{verbatim}
<d:decimal64 fraction-digits:4>;
<d:decimal64 fraction-digits:4 range[0.1:10]>;
\end{verbatim}
which allows numbers with four decimals. The econd example limits the numbers to be between 0.1000 and 10.0000.
Note that the {\tt fraction-digits} statement should come before the {\tt range} statement.
\subsection{Keyword}
\label{sec:keyword}
A keyword variable is just an alternative way of specifying command
keywords as defined in Section~\ref{sec:syntax}. In fact, a syntax
with static keywords can just as well be written using keyword
variables.
Thus, for example, the two specification lines below are equivalent:
\begin{verbatim}
aa bb;
<aa:string keyword:aa> <bb:string keyword:bb>;
\end{verbatim}
However, a keyword variable can have another name:
\begin{verbatim}
<myname:string keyword:aa>;
\end{verbatim}
Naming of keywords provides for more flexible search functions
in callbacks, see Section~\ref{sec:api}.
Note that a keyword must be of type {\tt string}.
\subsection{Choice}
The choice variable can take the value from a static list of elements.
Example:
\begin{verbatim}
interface <ifname:string choice:eth0|eth1>("Interface name");
\end{verbatim}
A CLI user will get the following choice:
\begin{verbatim}
cli> interface '?'
eth0 Interface name
eth1 Interface name
cli>
\end{verbatim}
The user can only select eth0 or eth1, and thus the value of the {\tt
ifname} variable is either {\tt eth0} or {\tt eth1}.
Note the resemblance with choice of strings in
Section~\ref{sec:operators} where the same example could be specified
as:
\begin{verbatim}
interface (eth0|eth1)
\end{verbatim}
Again, the former variant allows for naming of the variable which can
be better when writing a callback function. In the example, the name
of the variable in the first example is {\tt ifname} whereas in the
second it is \emph{either} {\tt eth0} or {\tt eth1}.
\subsection{Expand}
\label{sec:expand1}
The choice variable specifies a static list of
keywords. But what if the list is dynamic and changes over time?
The expansion variable is a \emph{dynamic} list of keywords, where the
list may be different each time the CLI command is invoked.
For example, assume a user can select a network interface in the CLI,
but the number of interfaces changes all the time. This can be
specified as follows:
\begin{verbatim}
interface <ifname:string interfaces()>("Interface name")
\end{verbatim}
The user's choice in the CLI will then be just as in the choice case:
\begin{verbatim}
cli> interface '?'
eth0 Interface name
eth1 Interface name
cli>
\end{verbatim}
However, at another point in time, the choice of interfaces may be different:
\begin{verbatim}
cli> interface '?'
eth3 Interface name
lo0 Interface name
cli>
\end{verbatim}
There is one catch here: the CLI needs to know in run-time the members
of the list. That is, the list members cannot be specified in the
syntax. In CLIgen, the application programmer defines a C callback
function, {\tt interfaces()} in this example, which computes the list
at the time it is needed. This callback is registered and called
whenever necessary.
How to write an expand callback is further described in
Section~\ref{sec:expand}.
\subsection{Regular expressions}
A string variable may be described using a regular expression. That
is, a regular expression defines which values are valid.
For example, a variable may be specified as:
\begin{verbatim}
<name:string regexp:"(ab|a)b*c">;
<name:string regexp:"[a-z]+[0-8]+\\.[0-9]">;
\end{verbatim}
The first rule matches the following strings, for example:
\begin{verbatim}
ac
abc
abbbbbbbbbc
\end{verbatim}
You can also add multiple regexps, in which case the string must match ALL regexps. You can also specify an inverted regex, meaning that a string should NOT match the regex.
In the following example, all strings are matched that do not start with "cli"
\begin{verbatim}
<name:string regexp:"[a-zA-Z]+" regexp:!"cli.*">;
\end{verbatim}
CLIgen by default uses POSIX Extended regular expression syntax.
However, XML schema regexps can be used instead by configuring CLIgen with libxml2 as follows:
\begin{verbatim}
./configure --with-libxml2 # At configure time
cligen_regexp_xsd\_set(h, 1); # In C init code
\end{verbatim}
\subsection{Variable translation}
CLIgen supports variable translation. A given variable can be
translated on-th-fly using a generic translation function. This may be useful for example when hashing or encrypting a value.
In the example below, the variable {\tt var} is translated by the function {\tt incstr}:
\begin{verbatim}
increment <var:string translate:incstr()>, cb();
\end{verbatim}
In this example, {\tt incstr} simply increments every character in the variable.
\begin{verbatim}
cli> increment HAL
variables: 1 name:var type:string value:IBM
\end{verbatim}
In the same way, a clear text password could be translated to an encrypted string.
For information on how to implement a translator function, see Section~\ref{sec:translate}.
\subsection{Variable preference}
There are situations when a command matches multiple variables, and CLIgen may return {\em Ambiguous command}. For this purpose, variable {\em preference} can resolve
tiebreaks.
For example, consider the CLI syntax:
\begin{verbatim}
mycommand;
<name:string regexp:"[a-z]+">;
<name:string>;
\end{verbatim}
If a user types the command {\tt mycommand}, it matches all three rules; typing {\tt foo}
matches the two variables; and {\tt foo42} matches only the last.
Variable types have a default preference to resolve tie-breaks like
these. The highest preference is the best match. In the example, the
command ``mycommand'' has the highest preference, thereafter the
regexp, and finally the unqualified string type.
This means that typing {\tt mycommand} matches the first command rule; {\tt foo}
matches the regexp rule; and {\tt foo42} matches the last string type.
The default variable preference table is available in Appendix~D.
\subsubsection{Resolving tie-breaks}
Even with default variable preferences, there may be cases where a
command matches several rules with the same same default
preference. For example, strings with regular expressions that overlap
as follows:
\begin{verbatim}
<name:string regexp:"[a-b]+">;
<name:string regexp:"[b-c]+">;
\end{verbatim}
If a user types the string {\tt bbb}, it matches both rules with equal preference, which results in {\em Ambiguous command} error in the CLI.
There are two methods in CLIgen to resolve this tie-break:
\begin{enumerate}
\item {\tt preference} keyword
\item {\tt cligen\_preference\_mode\_set()} API function
\end{enumerate}
\subsubsection{Preference keyword}
First, the {\tt preference} keyword alters the preference of a variable, such as in the following example:
\begin{verbatim}
<name:string regexp:"[a-b]+" preference:9>;
<name:string regexp:"[b-c]+">;
\end{verbatim}
The effect is that the default preference ($7$) is overruled ($9$) in the first rule and therefore preferred over the second.
\subsubsection{Preference API}
Second, using the {\tt cligen\_preference\_mode()} API, a tie-break can be
resolved by choosing the first matching command for {\em all}
preference tie-breaks in a system. This may be useful if one knows
that this does not pose a problem.
More specifically, if all cases of tie-breaks are on the following form:
\begin{verbatim}
(<name:string regexp:"[a-b]+"> | <name:string regexp:"[b-c]+">) A();
\end{verbatim}
it can be considered safe, since both options lead to the same result {\tt A()}.
However, you need to be careful if effects of the commands are different. For example, given the following syntax:
\begin{verbatim}
<name:string regexp:"[a-b]+">, A();
<name:string regexp:"[b-c]+"> { sub-command, B(); }
\end{verbatim}
In this example, the API method should be avoided, since choosing one of the two
options lead to different results, in one case {\tt A()} is called, in the other a sub-menu is selected.
\section{Operators}
\label{sec:operators}
In the regular syntax format, there are (implicit) sequence and choices. For example, the syntax
\begin{verbatim}
aa bb;
cc;
\end{verbatim}
defines a choice between the sequence {\tt aa bb} and {\tt cc}.
It is also possible to explicitly define choices, optional elements and syntactical groupings.
\subsection{Choice and grouping}
Explit choice between several elements can be made as follows:
\begin{verbatim}
(aa bb) | cc;
\end{verbatim}
which expresses the same syntax as above.
Help strings work as usual, but may \emph{not} be associated with
groupings:
\begin{verbatim}
aa (bb("help b") cc("help c") | dd("help d"));
\end{verbatim}
Choices may also be made with variables:
\begin{verbatim}
values (<int8> | <string> | <int64> | aa);