├── debian ├── libcligen.install ├── libcligen-dev.install ├── rules └── control ├── usage.pdf ├── .editorconfig ├── cligen_tutorial.pdf ├── fuzz ├── specs │ ├── commands.cli │ └── sets.cli ├── runfuzz.sh └── README.md ├── codecov.yml ├── .gitignore ├── test ├── sum.sh ├── all.sh ├── README.md ├── test_rest.sh ├── test_completion.sh ├── config.sh.in ├── test_commands.sh ├── test_comment.sh ├── mem.sh ├── test_tutorial.sh ├── test_hide.sh ├── test_scroll_wide.exp ├── test_scroll_wrap.exp ├── test_helpstrings.sh ├── test_pipe.sh ├── test_mode.sh ├── test_getline.sh ├── test_reftree.sh ├── test_escaping.sh ├── test_list.sh ├── test_preference.sh ├── test_var.sh ├── test_scroll.sh ├── test_compile.sh ├── lib.sh ├── test_expand.sh ├── test_sets.sh └── test_types.sh ├── scripts ├── version.sh └── build_deb.sh ├── .github └── workflows │ └── ci.yml ├── cligen_util.h ├── cligen_cvec_internal.h ├── cligen_buf_internal.h ├── cligen_print.h ├── cligen_custom.h ├── cligen_getline.h ├── cligen_regex.h ├── cligen_read.h ├── cligen_match.h ├── cligen_history.h ├── cligen_config.h.in ├── cligen_expand.h ├── cligen_buf.h ├── cligen_history_internal.h ├── cligen.h ├── cligen_io.h ├── README.md ├── cligen_result.h ├── cligen_cvec.h ├── cligen_callback.h ├── cligen_pt_head.h ├── tutorial.cli ├── cligen_parsetree.h ├── cligen_syntax.h ├── cligen_hello.c ├── cligen_parse.h ├── cligen_util.c ├── cligen_callback.c ├── cligen_cv_internal.h ├── configure.ac ├── cligen_handle_internal.h ├── cligen_result.c └── Makefile.in /debian/libcligen.install: -------------------------------------------------------------------------------- 1 | usr/local/lib /usr/ -------------------------------------------------------------------------------- /debian/libcligen-dev.install: -------------------------------------------------------------------------------- 1 | usr/local/include /usr/ -------------------------------------------------------------------------------- /usage.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clicon/cligen/HEAD/usage.pdf -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.{c,h}] 4 | indent_size = 4 5 | indent_style = space -------------------------------------------------------------------------------- /cligen_tutorial.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clicon/cligen/HEAD/cligen_tutorial.pdf -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # Uncomment this to turn on verbose mode. 3 | #export DH_VERBOSE=1 4 | 5 | %: 6 | dh $@ -------------------------------------------------------------------------------- /fuzz/specs/commands.cli: -------------------------------------------------------------------------------- 1 | prompt="cli> "; # Assignment of prompt 2 | comment="#"; # Same comment as in syntax 3 | treename="tutorial"; # Name of syntax (used when referencing) 4 | 5 | a,callback(); 6 | abc,callback(); 7 | abd { 8 | a,callback(); 9 | b,callback(); 10 | } 11 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | 4 | coverage: 5 | precision: 2 6 | round: down 7 | range: "70...100" 8 | 9 | parsers: 10 | gcov: 11 | branch_detection: 12 | conditional: yes 13 | loop: yes 14 | method: no 15 | macro: no 16 | 17 | comment: 18 | layout: "reach,diff,flags,files,footer" 19 | behavior: default 20 | require_changes: no 21 | -------------------------------------------------------------------------------- /fuzz/specs/sets.cli: -------------------------------------------------------------------------------- 1 | prompt="cli> "; # Assignment of prompt 2 | comment="#"; # Same comment as in syntax 3 | treename="sets"; # Name of syntax (used when referencing) 4 | 5 | a @{ 6 | , callback(); 7 | b b2, callback(); 8 | c, callback(); 9 | d, callback(); 10 | e , callback(); 11 | } 12 | b,callback(); @{ 13 | c, callback(); @{ 14 | d, callback(); 15 | e, callback(); 16 | } 17 | f,callback(); 18 | } 19 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: cligen 2 | Section: devel 3 | Priority: optional 4 | Maintainer: roma55592@yandex.ru 5 | Build-Depends: 6 | debhelper-compat (= 12), 7 | flex, 8 | bison, 9 | libnghttp2-dev, 10 | libssl-dev 11 | Standards-Version: 4.5.0 12 | 13 | Package: libcligen-dev 14 | Architecture: any 15 | Multi-Arch: foreign 16 | Depends: ${misc:Depends}, 17 | ${shlibs:Depends}, 18 | libcligen 19 | Description: Cligen development package 20 | 21 | Package: libcligen 22 | Architecture: any 23 | Multi-Arch: foreign 24 | Depends: ${misc:Depends}, 25 | ${shlibs:Depends} 26 | Description: Cligen library package -------------------------------------------------------------------------------- /fuzz/runfuzz.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Run a fuzzing test using american fuzzy lop 3 | set -eux 4 | 5 | if [ $# -ne 2 ]; then 6 | echo "usage: $0 \n" 7 | exit 255 8 | fi 9 | 10 | fspec=$1 11 | input=$2 12 | 13 | MEGS=500 # memory limit for child process (50 MB) 14 | 15 | # remove input and input dirs 16 | test ! -d input || rm -rf input 17 | test ! -d output || rm -rf output 18 | 19 | # create if dirs dont exists 20 | test -d input || mkdir input 21 | test -d output || mkdir output 22 | 23 | # Create input string 24 | cat > input/1.cli < /dev/null 2>&1 17 | errcode=$? 18 | if [ $errcode -ne 0 ]; then 19 | err=1 20 | echo -e "\e[31mError in $testfile errcode=$errcode" 21 | echo -ne "\e[0m" 22 | fi 23 | done 24 | if [ $err -eq 0 ]; then 25 | echo OK 26 | else 27 | echo -e "\e[31mError" 28 | echo -ne "\e[0m" 29 | exit -1 30 | fi 31 | 32 | 33 | -------------------------------------------------------------------------------- /test/all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Run, eg as: 3 | # ./all.sh 2>&1 | tee test.log # break on first test 4 | 5 | # Pattern to run tests, default is all, but you may want to narrow it down 6 | : ${pattern:=test_*.sh} 7 | 8 | if [ $# -gt 0 ]; then 9 | echo "usage: $0 # detailed logs and stop on first error. Use pattern=\"\" $0 to" 10 | echo " Use pattern= $0 to narrow down test cases" 11 | exit -1 12 | fi 13 | 14 | err=0 15 | testnr=0 16 | for test in $pattern; do 17 | if [ $testnr != 0 ]; then echo; fi 18 | testfile=$test 19 | . ./$test 20 | errcode=$? 21 | if [ $errcode -ne 0 ]; then 22 | err=1 23 | echo -e "\e[31mError in $test errcode=$errcode" 24 | echo -ne "\e[0m" 25 | exit $errcode 26 | fi 27 | done 28 | if [ $err -eq 0 ]; then 29 | echo OK 30 | else 31 | echo -e "\e[31mError" 32 | echo -ne "\e[0m" 33 | exit -1 34 | fi 35 | 36 | 37 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | # CLIgen tests 2 | 3 | ## Overview 4 | 5 | Tests called `test_*.sh` and placed in this directory are 6 | automatically run as part of `all.sh` and `sum.sh` tests. The scripts 7 | need to follow some rules to work properly, please look at one or two 8 | to get the idea. 9 | 10 | ## Prereqs 11 | 12 | expect, valgrind 13 | 14 | ## Run tests 15 | 16 | You can run an individual test by itself, or run through all tests matching 'test_*.sh' in the directory. Prints test output and stops on first error: 17 | ``` 18 | all.sh 19 | ``` 20 | 21 | Run all tests but continue after errors and only print a summary test output identifying which tests succeeded and which failed: 22 | ``` 23 | sum.sh 24 | ``` 25 | 26 | ## Memory leak test 27 | The `mem.sh` runs memory checks using valgrind. If you 28 | ``` 29 | mem.sh 2>&1 | tee mylog 30 | ``` 31 | 32 | ## Run pattern of tests 33 | 34 | The above scripts work with the `pattern` variable to limit the scope of which tests run, eg: 35 | ``` 36 | pattern="test_c*.sh" mem.sh 37 | ``` -------------------------------------------------------------------------------- /scripts/version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # Version script 3 | # Usage: 4 | # ./version.sh 5 | # with optional fields: 6 | # PREFIX= INDEX=1 ARCH= SUFFIX= 7 | # Example: 8 | # PREFIX=cligen INDEX=1 ARCH=amd64 SUFFIX=deb ./version.sh 9 | set -eu 10 | : ${PREFIX:=} 11 | : ${INDEX=1} 12 | : ${ARCH=} 13 | : ${SUFFIX=} 14 | # Get version string from default git describe: --g 15 | if [ -f .version ]; then 16 | v1=$(cat .version) 17 | else 18 | v1=$(git describe) 19 | fi 20 | if [ -z $v1 ]; then 21 | echo "No base version" 22 | exit 1 23 | fi 24 | TAG=$(echo $v1 | awk -F- '{print $1}') 25 | NR=$(echo $v1 | awk -F- '{print $2}') 26 | HASH=$(echo $v1 | awk -F- '{print $3}') 27 | V="" 28 | if [ -n "$PREFIX" ]; then 29 | V="${V}${PREFIX}_" 30 | fi 31 | V="${V}${TAG}" 32 | V="${V}-${INDEX}" 33 | if [ -n "${NR}" ]; then 34 | V="${V}+${NR}" 35 | fi 36 | if [ -n "${HASH}" ]; then 37 | V="${V}+${HASH}" 38 | fi 39 | if [ -n "$ARCH" ]; then 40 | V="${V}_${ARCH}" 41 | fi 42 | if [ -n "$SUFFIX" ]; then 43 | V="${V}.${SUFFIX}" 44 | fi 45 | echo "${V}" 46 | -------------------------------------------------------------------------------- /fuzz/README.md: -------------------------------------------------------------------------------- 1 | # CLIgen fuzzing 2 | 3 | This dir contains code for fuzzing cligen. 4 | 5 | ## Prereqs 6 | 7 | See [AFL docs](https://afl-1.readthedocs.io/en/latest) for installing afl. 8 | 9 | You may have to change cpu frequency: 10 | ``` 11 | cd /sys/devices/system/cpu 12 | echo performance | tee cpu?/cpufreq/scaling_governor 13 | ``` 14 | 15 | And possibly change core behaviour: 16 | ``` 17 | echo core >/proc/sys/kernel/core_pattern 18 | ``` 19 | 20 | ## Build 21 | 22 | CLIgen must be built statically, eg as follows: 23 | ``` 24 | CC=/usr/bin/afl-gcc CXX=/usr/bin/afl-g++ LINKAGE=static ./configure 25 | make clean 26 | make 27 | ``` 28 | 29 | ## Run tests 30 | 31 | Use the script `runfuzz.sh` to run one test with a cli spec and an input string, eg: 32 | ``` 33 | ./runfuzz.sh ./specs/commands.cli "abd a" 34 | ./runfuzz.sh ./specs/sets.cli "b f c d ?" 35 | ``` 36 | 37 | CLIgen specs are taken from the [test dir](../test). 38 | 39 | After (or during) the test, investigate results in the output dir. 40 | 41 | Note that one test is done at a time, you cannot run concurrent tests this way, since there is a single output dir. 42 | 43 | 44 | -------------------------------------------------------------------------------- /scripts/build_deb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | # 6 | # This script is used to build Debian packages for Cligen. 7 | # 8 | 9 | # Make sure the script is started from the cligen directory 10 | if [ ! -f scripts/version.sh ]; then 11 | echo "This script must be run from the cligen directory." 12 | exit 1 13 | fi 14 | 15 | VERSION=$(./scripts/version.sh) 16 | 17 | if [ $? -ne 0 ]; then 18 | echo "Failed to determine the version of Cligen." 19 | exit 1 20 | fi 21 | 22 | # Create the build/ directory 23 | if [ ! -d build ]; then 24 | mkdir build 25 | fi 26 | 27 | # Copy the debian/ directory to the build/ directory 28 | if [ ! -d build/debian ]; then 29 | cp -r debian build/ 30 | fi 31 | 32 | # Update the change log 33 | echo -n "cligen (${VERSION}) " > build/debian/changelog 34 | 35 | git --no-pager log --no-walk --encoding=utf-8 --expand-tabs=4 --pretty=format:"${VERSION} stable; urgency=medium%n%n * %w(,,2)%B%w()%n -- %an <%ae> %aD%n" >> build/debian/changelog 36 | 37 | if [ $? -ne 0 ]; then 38 | echo "Failed to update the change log." 39 | exit 1 40 | fi 41 | 42 | # Build Cligen and install it to the build/ directory 43 | ./configure && make clean && make && make install DESTDIR=build/ 44 | 45 | if [ $? -ne 0 ]; then 46 | echo "Failed to build Cligen." 47 | exit 1 48 | fi 49 | 50 | # Build the package 51 | (cd build && dpkg-buildpackage -us -uc) 52 | 53 | if [ $? -ne 0 ]; then 54 | echo "Failed to build the package." 55 | exit 1 56 | fi 57 | -------------------------------------------------------------------------------- /test/test_rest.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # CLI rest 3 | 4 | # Magic line must be first in script (see README.md) 5 | s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi 6 | 7 | fspec=$dir/spec.cli 8 | 9 | cat > $fspec <,callback(); 17 | aa,callback(); 18 | } 19 | xxx , callback(); 20 | EOF 21 | 22 | newtest "$cligen_file -f $fspec" 23 | 24 | newtest "cligen values aa command" 25 | expectpart "$(echo "values aa" | $cligen_file -f $fspec 2>&1)" 0 "1 name:values type:string value:values" "2 name:aa type:string value:aa" 26 | 27 | # DOESNT WORK - DIDNT WORK in 4.4 either phew 28 | #newtest "cligen values aa bb rest" 29 | #expectpart "$(echo "values aa bb" | $cligen_file -f $fspec 2>&1)" 0 "1 name:values type:string value:values" "2 name:x type:rest value:aa bb" 30 | 31 | newtest "cligen values aab rest" 32 | expectpart "$(echo "values aab" | $cligen_file -f $fspec 2>&1)" 0 "1 name:values type:string value:values" "2 name:x type:rest value:aab" 33 | 34 | newtest "cligen values aab foo rest" 35 | expectpart "$(echo "values aab cde" | $cligen_file -f $fspec 2>&1)" 0 "1 name:values type:string value:values" "2 name:x type:rest value:aab cde" 36 | 37 | newtest "endtest" 38 | endtest 39 | 40 | rm -rf $dir 41 | 42 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CLIgen CI 2 | 3 | on: 4 | 5 | push: 6 | branches: 7 | - master 8 | - test-actions 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | ubuntu-build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | with: 20 | fetch-depth: 0 21 | - name: install expect 22 | run: sudo apt install -y expect 23 | - name: configure 24 | run: ./configure 25 | - name: make 26 | run: make 27 | - name: make install 28 | run: sudo make install 29 | - name: ldconfig 30 | run: sudo ldconfig 31 | - name: make test 32 | run: make test 33 | 34 | ubuntu-coverage: 35 | needs: ubuntu-build 36 | runs-on: ubuntu-latest 37 | 38 | steps: 39 | - uses: actions/checkout@v4 40 | with: 41 | fetch-depth: 0 42 | - name: install expect 43 | run: sudo apt install -y expect 44 | - name: configure w coverage 45 | run: ./configure CPPFLAGS="-fprofile-arcs -ftest-coverage -O0" CFLAGS="" LDFLAGS="-fprofile-arcs -lgcov" 46 | - name: make 47 | run: make 48 | - name: make install 49 | run: sudo make install 50 | - name: ldconfig 51 | run: sudo ldconfig 52 | - name: make test 53 | run: make test 54 | - name: Upload coverage to Codecov 55 | uses: codecov/codecov-action@v4 56 | with: 57 | verbose: true 58 | token: ${{ secrets.CODECOV_TOKEN }} 59 | -------------------------------------------------------------------------------- /test/test_completion.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # CLI completion functionality 3 | # Test s simple spec "value " and try tabs in different variations 4 | 5 | # Magic line must be first in script (see README.md) 6 | s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi 7 | 8 | fspec=$dir/spec.cli 9 | 10 | cat > $fspec < | aa), callback(); 20 | 21 | EOF 22 | 23 | newtest "$cligen_file -f $fspec" 24 | 25 | newtest "empty?" 26 | expectpart "$(echo "?" | $cligen_file -f $fspec )" 0 "cli>" "values" "vb" 27 | 28 | newtest "empty" 29 | expectpart "$(echo " " | $cligen_file -f $fspec )" 0 "cli> v " "Ambiguous command" 30 | 31 | newtest "empty" 32 | expectpart "$(echo " " | $cligen_file -f $fspec )" 0 "cli> v" "values vb" 33 | 34 | newtest "v ambiguous" 35 | expectpart "$(echo "v " | $cligen_file -f $fspec )" 0 "values vb" "Ambiguous command" 36 | 37 | newtest "va incomplete" 38 | expectpart "$(echo "v a " | $cligen_file -f $fspec)" 0 "values vb" "cli> values" 'CLI syntax error in: "values": Incomplete command' 39 | 40 | newtest "va42 OK" 41 | expectpart "$(echo "v a 42" | $cligen_file -f $fspec 2>&1)" 0 "cli> values 42" "1 name:values type:string value:values" "2 name:int32 type:int32 value:42" 42 | 43 | newtest "endtest" 44 | endtest 45 | 46 | rm -rf $dir 47 | -------------------------------------------------------------------------------- /test/config.sh.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # ***** BEGIN LICENSE BLOCK ***** 3 | # 4 | # Copyright (C) 2001-2022 Olof Hagsand 5 | # 6 | # This file is part of CLIgen. 7 | # 8 | # Licensed under the Apache License, Version 2.0 (the "License"); 9 | # you may not use this file except in compliance with the License. 10 | # You may obtain a copy of the License at 11 | # 12 | # http://www.apache.org/licenses/LICENSE-2.0 13 | # 14 | # Unless required by applicable law or agreed to in writing, software 15 | # distributed under the License is distributed on an "AS IS" BASIS, 16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | # See the License for the specific language governing permissions and 18 | # limitations under the License. 19 | # 20 | # Alternatively, the contents of this file may be used under the terms of 21 | # the GNU General Public License Version 2 or later (the "GPL"), 22 | # in which case the provisions of the GPL are applicable instead 23 | # of those above. If you wish to allow use of your version of this file only 24 | # under the terms of the GPL, and not to allow others to 25 | # use your version of this file under the terms of Apache License version 2, indicate 26 | # your decision by deleting the provisions above and replace them with the 27 | # notice and other provisions required by the GPL. If you do not delete 28 | # the provisions above, a recipient may use your version of this file under 29 | # the terms of any one of the Apache License version 2 or the GPL. 30 | # 31 | # ***** END LICENSE BLOCK ***** 32 | # 33 | # Generated from autotools, ie from the ./configure run, 34 | # See configure.ac for source 35 | # See also site.sh 36 | 37 | # C compiler 38 | CC=@CC@ 39 | 40 | 41 | -------------------------------------------------------------------------------- /test/test_commands.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # CLI simple commands: ambiguous, unknown, perfect match 3 | 4 | # Magic line must be first in script (see README.md) 5 | s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi 6 | 7 | fspec=$dir/spec.cli 8 | 9 | cat > $fspec <, cligen_exec_cb("echo \$a"); # Trivial: just echo 21 | EOF 22 | 23 | newtest "$cligen_file -f $fspec" 24 | 25 | newtest "b unknown" 26 | expectpart "$(echo "b" | $cligen_file -f $fspec)" 0 "Unknown command" 27 | 28 | newtest "a OK" 29 | expectpart "$(echo "a" | $cligen_file -f $fspec 2>&1)" 0 "1 name:a type:string value:a" 30 | 31 | newtest "ab ambiguous" 32 | expectpart "$(echo "ab" | $cligen_file -f $fspec)" 0 "Ambiguous command" 33 | 34 | newtest "ab ambiguous preference mode" 35 | expectpart "$(echo "ab" | $cligen_file -P 1 -f $fspec 2>&1)" 0 "Ambiguous command" 36 | 37 | newtest "abc ok" 38 | expectpart "$(echo "abc" | $cligen_file -f $fspec 2>&1)" 0 "1 name:abc type:string value:abc" 39 | 40 | newtest "abd incomplete" 41 | expectpart "$(echo "abd" | $cligen_file -f $fspec 2>&1)" 0 'CLI syntax error in: "abd": Incomplete command' 42 | 43 | newtest "run hello" 44 | expectpart "$(echo "hello world" | $cligen_hello 2>&1)" 0 'hello world' 45 | 46 | newtest "run exec" 47 | expectpart "$(echo "exec foo" | $cligen_file -f $fspec 2>&1)" 0 foo 48 | 49 | newtest "endtest" 50 | endtest 51 | 52 | rm -rf $dir 53 | 54 | -------------------------------------------------------------------------------- /cligen_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | CLI generator input/output support functions. 3 | 4 | ***** BEGIN LICENSE BLOCK ***** 5 | 6 | Copyright (C) 2001-2022 Olof Hagsand 7 | 8 | This file is part of CLIgen. 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); 11 | you may not use this file except in compliance with the License. 12 | You may obtain a copy of the License at 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | Unless required by applicable law or agreed to in writing, software 17 | distributed under the License is distributed on an "AS IS" BASIS, 18 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | See the License for the specific language governing permissions and 20 | limitations under the License. 21 | 22 | Alternatively, the contents of this file may be used under the terms of 23 | the GNU General Public License Version 2 or later (the "GPL"), 24 | in which case the provisions of the GPL are applicable instead 25 | of those above. If you wish to allow use of your version of this file only 26 | under the terms of the GPL, and not to allow others to 27 | use your version of this file under the terms of Apache License version 2, indicate 28 | your decision by deleting the provisions above and replace them with the 29 | notice and other provisions required by the GPL. If you do not delete 30 | the provisions above, a recipient may use your version of this file under 31 | the terms of any one of the Apache License version 2 or the GPL. 32 | 33 | ***** END LICENSE BLOCK ***** 34 | 35 | This file includes utility functions (good-to-have) for CLIgen applications 36 | */ 37 | 38 | #ifndef _CLIGEN_UTIL_H_ 39 | #define _CLIGEN_UTIL_H_ 40 | 41 | /* 42 | * Prototypes 43 | */ 44 | int cvec_add_string(cvec *cvv, const char *name, const char *val); 45 | 46 | int cligen_loop(cligen_handle h); 47 | 48 | #endif /* _CLIGEN_UTIL_H_ */ 49 | -------------------------------------------------------------------------------- /test/test_comment.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # CLIgen comment (runtime not clispec) 3 | 4 | # Magic line must be first in script (see README.md) 5 | s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi 6 | 7 | fspec=$dir/spec.cli 8 | 9 | cat > $fspec <, callback(); 17 | } 18 | EOF 19 | 20 | newtest "$cligen_file -f $fspec" 21 | 22 | newtest "comment line" 23 | expectpart "$(echo "# Comment" | $cligen_file -f $fspec)" 0 "cli> # Comment" 24 | 25 | newtest "comment whitespace line" 26 | expectpart "$(echo " # Comment" | $cligen_file -f $fspec)" 0 "# Comment" 27 | 28 | newtest "comment after command" 29 | expectpart "$(echo "abc # Comment" | $cligen_file -f $fspec 2>&1)" 0 "cli> abc # Comment" "1 name:abc type:string value:abc" 30 | 31 | newtest "comment in command" 32 | expectpart "$(echo "abc#Comment" | $cligen_file -f $fspec 2>&1)" 0 "cli> abc#Comment" "CLI syntax error in: \"abc#Comment\": Unknown command" --not-- "1 name:abc type:rest value:abc#Comment" 33 | 34 | newtest "comment after command+str" 35 | expectpart "$(echo "abc str # Comment" | $cligen_file -f $fspec 2>&1)" 0 "cli> abc str # Comment" "1 name:abc type:string value:abc" "2 name:s type:rest value:str" 36 | 37 | newtest "comment in str" 38 | expectpart "$(echo "abc str#Comment" | $cligen_file -f $fspec 2>&1)" 0 "cli> abc str#Comment" "1 name:abc type:string value:abc" "2 name:s type:rest value:str#Comment" 39 | 40 | newtest "comment in rest" 41 | expectpart "$(echo "abc str s# Comment" | $cligen_file -f $fspec 2>&1)" 0 "cli> abc str s# Comment" "1 name:abc type:string value:abc" "2 name:s type:rest value:str s# Comment" 42 | 43 | newtest "endtest" 44 | endtest 45 | 46 | rm -rf $dir 47 | 48 | -------------------------------------------------------------------------------- /test/mem.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Run valgrind leak test for cligen 3 | # Stop on first error 4 | # Typical run: ./mem.sh 2>&1 | tee mylog 5 | 6 | # Pattern to run tests, default is all, but you may want to narrow it down 7 | : ${pattern:=test_*.sh} 8 | 9 | # Run valgrindtest once, args: 10 | # what: (cli|netconf|restconf|backend)* # no args means all 11 | memonce(){ 12 | 13 | valgrindfile=$(mktemp) 14 | echo "valgrindfile:$valgrindfile" 15 | valgrindtest=1 16 | # : ${RCWAIT:=5} # valgrind backend needs some time to get up 17 | # --suppressions=./valgrind-clixon.supp 18 | cligen_file="/usr/bin/valgrind --leak-check=full --show-leak-kinds=all --track-fds=yes --trace-children=no --child-silent-after-fork=yes --log-file=$valgrindfile ../cligen_file" 19 | cligen_tutorial="/usr/bin/valgrind --leak-check=full --show-leak-kinds=all --track-fds=yes --trace-children=no --child-silent-after-fork=yes --log-file=$valgrindfile ../cligen_tutorial" 20 | 21 | err=0 22 | for test in $pattern; do 23 | if [ $testnr != 0 ]; then echo; fi 24 | testfile=$test 25 | . ./$test 26 | errcode=$? 27 | if [ $errcode -ne 0 ]; then 28 | err=1 29 | echo -e "\e[31mError in $test errcode=$errcode" 30 | echo -ne "\e[0m" 31 | exit $errcode 32 | fi 33 | done 34 | if [ $valgrindtest -eq 1 ]; then 35 | checkvalgrind 36 | sudo rm -f $valgrindfile 37 | fi 38 | } 39 | 40 | # Print a line with ==== under 41 | println(){ 42 | str=$1 43 | echo "$str" 44 | length=$(echo "$str" | wc -c) 45 | let i=1 46 | while [ $i -lt $length ]; do 47 | echo -n "=" 48 | let i++ 49 | done 50 | echo 51 | } 52 | 53 | # Then actual run 54 | testnr=0 55 | if [ $testnr != 0 ]; then echo; fi 56 | println "Mem test cligen begin" 57 | memonce $cmd1 58 | println "Mem test cligen done" 59 | 60 | 61 | unset pattern 62 | -------------------------------------------------------------------------------- /test/test_tutorial.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Run through the tutorial example 3 | 4 | # Magic line must be first in script (see README.md) 5 | s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi 6 | 7 | fspec=../tutorial.cli 8 | 9 | newtest "$cligen_tutorial -f $fspec" 10 | 11 | newtest "? TAB" 12 | expectpart "$(echo "? " | $cligen_tutorial -f $fspec)" 0 access-list 13 | 14 | newtest "aa bb ca 42" 15 | expectpart "$(echo "aa bb ca 42" | $cligen_tutorial -q -f $fspec)" 0 ca 16 | 17 | newtest "access-list permit 1.2.3.4 4.3.2.1" 18 | expectpart "$(echo "access-list permit 1.2.3.4 4.3.2.1" | $cligen_tutorial -q -f $fspec)" 0 'access-list' 19 | 20 | newtest "add x y" 21 | expectpart "$(echo "add x y" | $cligen_tutorial -q -f $fspec 2>&1)" 0 'arg 0: a' 22 | 23 | newtest "change prompt foobar>\ " 24 | expectpart "$(echo "change prompt \"foobar> \"" | $cligen_tutorial -q -f $fspec)" 0 'foobar' 25 | 26 | newtest "ex ?" 27 | expectpart "$(echo "ex ?" | $cligen_tutorial -q -f $fspec)" 0 'A number' 28 | 29 | newtest "hello" 30 | expectpart "$(echo "hello world" | $cligen_tutorial -q -f $fspec)" 0 'Hello World!' 31 | 32 | newtest "translate: increment" 33 | expectpart "$(echo "increment 23" | $cligen_tutorial -q -f $fspec 2>&1)" 0 'value:34' 34 | 35 | newtest "interface" 36 | expectpart "$(echo "interface eth0" | $cligen_tutorial -q -f $fspec 2>&1)" 0 'value:eth0' 37 | 38 | newtest "ip tcp" 39 | expectpart "$(echo "ip tcp 8080" | $cligen_tutorial -q -f $fspec 2>&1)" 0 'value:8080' 40 | 41 | newtest "recurse" 42 | expectpart "$(echo "recurse recurse hello world" | $cligen_tutorial -q -f $fspec 2>&1)" 0 'Hello World!' 43 | 44 | newtest "secret" 45 | expectpart "$(echo "secret" | $cligen_tutorial -q -f $fspec 2>&1)" 0 'This is a hidden command' 46 | 47 | newtest "values int64" 48 | expectpart "$(echo "values 42676767676" | $cligen_tutorial -q -f $fspec 2>&1)" 0 'int64' --not-- int32 49 | 50 | newtest "endtest" 51 | endtest 52 | 53 | rm -rf $dir 54 | -------------------------------------------------------------------------------- /test/test_hide.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # CLIgen comment (runtime not clispec) 3 | 4 | # Magic line must be first in script (see README.md) 5 | s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi 6 | 7 | fspec=$dir/spec.cli 8 | 9 | cat > $fspec <, hide, callback(); 16 | ab0 , callback(); 17 | } 18 | b00, callback();{ 19 | ba0, hide{ 20 | , callback(); 21 | } 22 | bb0 { 23 | bca, callback(); 24 | bcb,hide { 25 | , callback(); 26 | } 27 | } 28 | bc0, hide{ 29 | bda, callback(); 30 | bdb , callback(); 31 | } 32 | } 33 | EOF 34 | 35 | newtest "$cligen_file -f $fspec" 36 | 37 | newtest "top level a00 hidden" 38 | expectpart "$(echo "?" | $cligen_file -f $fspec)" 0 "b00" --not-- "a00" 39 | 40 | newtest "first level hidden" 41 | expectpart "$(echo "a00 ?  " | $cligen_file -f $fspec)" 0 --not-- "aa0" "ab0" 42 | 43 | newtest "second level command" 44 | expectpart "$(echo "a00 ab0 str" | $cligen_file -f $fspec 2>&1)" 0 "0 name:cmd type:rest value:a00 ab0 str" "1 name:a00 type:string value:a00" "2 name:ab0 type:string value:ab0" "3 name:s type:string value:str" 45 | 46 | newtest "first level shown" 47 | expectpart "$(echo "b00 ?  " | $cligen_file -f $fspec)" 0 bb0 --not-- ba0 bc0 48 | 49 | newtest "second level shown" 50 | expectpart "$(echo "b00 bb0 ?  " | $cligen_file -f $fspec)" 0 bca --not-- bcb 51 | 52 | newtest "third level command" 53 | expectpart "$(echo "b00 bb0 bcb foo" | $cligen_file -f $fspec 2>&1)" 0 "0 name:cmd type:rest value:b00 bb0 bcb foo" "1 name:b00 type:string value:b00" "2 name:bb0 type:string value:bb0" "3 name:bcb type:string value:bcb" "4 name:s type:string value:foo" 54 | 55 | newtest "endtest" 56 | endtest 57 | 58 | rm -rf $dir 59 | 60 | -------------------------------------------------------------------------------- /test/test_scroll_wide.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env expect -f 2 | # Tests of more/scrolling for 20 rows and 128 width: no wrapping 3 | 4 | set timeout 1 5 | #log_user 0 6 | 7 | set stty_init "rows 20 cols 128" 8 | 9 | send_user "\nTest Wide lines no wrapping\n" 10 | 11 | set fspec [lindex $argv 0] 12 | spawn ../cligen_file -f $fspec 13 | 14 | send "command\n" 15 | 16 | expect { 17 | timeout { send_user "\nline 18 not received.\n"; exit 1} 18 | "arg 18: line18-abcdefghijklmnopqrstuvw" { send_user "\nline 18 OK.\n";} 19 | } 20 | 21 | expect { 22 | timeout { send_user "\nline 19 received.\n";} 23 | "arg 19: line19-abcdefghijklmnopqrstuvw" { send_user "\nline 19 not expected.\n"; exit 1} 24 | } 25 | 26 | expect { 27 | timeout { send_user "\nMore 1 not received.\n"; exit 1} 28 | -ex "--More--" {send_user "\nMore 1 OK.\n"} 29 | } 30 | 31 | send "\n" 32 | 33 | expect { 34 | timeout { send_user "\nline 19 not received.\n"; exit 1} 35 | "arg 19: line19-abcdefghijklmnopqrstuvw" { send_user "\nline 19 OK.\n"} 36 | } 37 | 38 | expect { 39 | "arg 20: line20-abcdefghijklmnopqrstuvw" { send_user "\nline 19 not expected.\n"; exit 1} 40 | } 41 | 42 | expect { 43 | timeout { send_user "\nMore 2 not received.\n"; exit 1} 44 | -ex "--More--" { send_user "\nMore 2 OK.\n"} 45 | } 46 | 47 | send " " 48 | 49 | expect { 50 | timeout { send_user "\nline 20 not received.\n"; exit 1} 51 | "arg 20: line20-abcdefghijklmnopqrstuvw" {send_user "\nLine 20 OK.\n" } 52 | } 53 | 54 | expect { 55 | timeout { send_user "\nline 38 not received.\n"; exit 1} 56 | "arg 38: line38-abcdefghijklmnopqrstuvw" { send_user "\Line 38 OK.\n" } 57 | } 58 | 59 | expect { 60 | timeout { send_user "\nMore 3 not received.\n"; exit 1} 61 | -ex "--More--" { send_user "\nMore 3 OK.\n" } 62 | } 63 | 64 | send "q" 65 | 66 | expect { 67 | "arg 39: line39-abcdefghijklmnopqrstuvw" { send_user "\nline 39 not expected.\n"; exit 1} 68 | } 69 | 70 | expect { 71 | -ex "--More--" { send_user "\nMore not expected.\n"; exit 1} 72 | } 73 | 74 | send "\d" 75 | close 76 | 77 | send_user "\nTest OK\n" 78 | -------------------------------------------------------------------------------- /cligen_cvec_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | ***** BEGIN LICENSE BLOCK ***** 3 | 4 | Copyright (C) 2001-2022 Olof Hagsand 5 | 6 | This file is part of CLIgen. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | Alternatively, the contents of this file may be used under the terms of 21 | the GNU General Public License Version 2 or later (the "GPL"), 22 | in which case the provisions of the GPL are applicable instead 23 | of those above. If you wish to allow use of your version of this file only 24 | under the terms of the GPL, and not to allow others to 25 | use your version of this file under the terms of Apache License version 2, indicate 26 | your decision by deleting the provisions above and replace them with the 27 | notice and other provisions required by the GPL. If you do not delete 28 | the provisions above, a recipient may use your version of this file under 29 | the terms of any one of the Apache License version 2 or the GPL. 30 | 31 | ***** END LICENSE BLOCK ***** 32 | 33 | * This is an internal CLIgen header file 34 | * Do not use these struct for external use, the internal structure may change. 35 | * @see cligen_cvec.h for external API use 36 | */ 37 | 38 | #ifndef _CLIGEN_CVEC_INTERNAL_H_ 39 | #define _CLIGEN_CVEC_INTERNAL_H_ 40 | 41 | /* 42 | * Types 43 | */ 44 | struct cvec{ 45 | cg_var *vr_vec; /* vector of CLIgen variables */ 46 | int vr_len; /* length of vector */ 47 | char *vr_name; /* name of cvec, can be NULL */ 48 | }; 49 | 50 | #endif /* _CLIGEN_CVEC_INTERNAL_H_ */ 51 | -------------------------------------------------------------------------------- /cligen_buf_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | ***** BEGIN LICENSE BLOCK ***** 3 | 4 | Copyright (C) 2001-2022 Olof Hagsand 5 | 6 | This file is part of CLIgen. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | Alternatively, the contents of this file may be used under the terms of 21 | the GNU General Public License Version 2 or later (the "GPL"), 22 | in which case the provisions of the GPL are applicable instead 23 | of those above. If you wish to allow use of your version of this file only 24 | under the terms of the GPL, and not to allow others to 25 | use your version of this file under the terms of Apache License version 2, indicate 26 | your decision by deleting the provisions above and replace them with the 27 | notice and other provisions required by the GPL. If you do not delete 28 | the provisions above, a recipient may use your version of this file under 29 | the terms of any one of the Apache License version 2 or the GPL. 30 | 31 | ***** END LICENSE BLOCK ***** 32 | * 33 | * This is an internal CLIgen header file 34 | * Do not use these struct for external use, the internal structure may change. 35 | * @see cligen_buf.h for external API use 36 | */ 37 | 38 | #ifndef _CLIGEN_BUF_INTERNAL_H 39 | #define _CLIGEN_BUF_INTERNAL_H 40 | 41 | /* 42 | * Types 43 | */ 44 | /*! Internal CLIgen buffer. 45 | */ 46 | struct cbuf { 47 | char *cb_buffer; /* pointer to buffer */ 48 | size_t cb_buflen; /* allocated bytes of buffer */ 49 | size_t cb_strlen; /* length of string in buffer (< buflen) */ 50 | }; 51 | 52 | #endif /* _CLIGEN_BUF_INTERNAL_H */ 53 | -------------------------------------------------------------------------------- /cligen_print.h: -------------------------------------------------------------------------------- 1 | /* 2 | ***** BEGIN LICENSE BLOCK ***** 3 | 4 | Copyright (C) 2001-2022 Olof Hagsand 5 | 6 | This file is part of CLIgen. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | Alternatively, the contents of this file may be used under the terms of 21 | the GNU General Public License Version 2 or later (the "GPL"), 22 | in which case the provisions of the GPL are applicable instead 23 | of those above. If you wish to allow use of your version of this file only 24 | under the terms of the GPL, and not to allow others to 25 | use your version of this file under the terms of Apache License version 2, indicate 26 | your decision by deleting the provisions above and replace them with the 27 | notice and other provisions required by the GPL. If you do not delete 28 | the provisions above, a recipient may use your version of this file under 29 | the terms of any one of the Apache License version 2 or the GPL. 30 | 31 | ***** END LICENSE BLOCK ***** 32 | */ 33 | 34 | #ifndef _CLIGEN_PRINT_H_ 35 | #define _CLIGEN_PRINT_H_ 36 | 37 | /* 38 | * Prototypes 39 | */ 40 | int cov2cbuf(cbuf *cb, cg_obj *co, int brief); 41 | int pt_print1(FILE *f, parse_tree *pt, int brief); 42 | int pt_print(FILE *f, parse_tree *pt); 43 | int co_print1(FILE *f, cg_obj *co, int brief); 44 | int co_print(FILE *f, cg_obj *co); 45 | int cligen_print_trees(FILE *f, cligen_handle h, int brief); 46 | int callbacks_dump(FILE *f, cg_callback *cc0); 47 | int co_dump(FILE *f, cg_obj *co); 48 | int pt_dump(FILE *f, parse_tree *pt); 49 | 50 | /* Backward compatible */ 51 | #define cligen_print(f, h, b) pt_print((f), (h), (b)) 52 | 53 | #endif /* _CLIGEN_PRINT_H_ */ 54 | -------------------------------------------------------------------------------- /cligen_custom.h: -------------------------------------------------------------------------------- 1 | /* 2 | ***** BEGIN LICENSE BLOCK ***** 3 | 4 | Copyright (C) 2001-2022 Olof Hagsand 5 | 6 | This file is part of CLIgen. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | Alternatively, the contents of this file may be used under the terms of 21 | the GNU General Public License Version 2 or later (the "GPL"), 22 | in which case the provisions of the GPL are applicable instead 23 | of those above. If you wish to allow use of your version of this file only 24 | under the terms of the GPL, and not to allow others to 25 | use your version of this file under the terms of Apache License version 2, indicate 26 | your decision by deleting the provisions above and replace them with the 27 | notice and other provisions required by the GPL. If you do not delete 28 | the provisions above, a recipient may use your version of this file under 29 | the terms of any one of the Apache License version 2 or the GPL. 30 | 31 | ***** END LICENSE BLOCK ***** 32 | 33 | Custom file as boilerplate appended by cligen_config.h 34 | */ 35 | 36 | #if 1 /* SANITY CHECK */ 37 | typedef struct {int a;} *cligen_handle; 38 | #else 39 | typedef void *cligen_handle; /* API */ 40 | #endif 41 | 42 | /*! Do not match partial matches of expanded commands 43 | * 44 | * During command parsing, if a user enters a value that partially matches an existing configured value, 45 | * the error is silently discarded. 46 | * Example, set a mac-address: 47 | * cli> set macaddress 00:11:22:33:44:55 48 | * cli> set macaddress 00: 49 | * See https://github.com/clicon/cligen/issues/133 50 | * Should probably always be set 51 | */ 52 | #undef CLIGEN_DONT_MATCH_PARTIAL_EXPANDS 53 | -------------------------------------------------------------------------------- /test/test_scroll_wrap.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env expect -f 2 | # Tests of more/scrolling for 20 rows and 100 width: wrapping of all except first line 3 | # Note that the line is written in two chunks by the cligen_file() callback routine, 4 | # First "arg %d:" , Then " line%d-abcdefgc.....\n" 5 | # 100 width is more than the second part 6 | 7 | set timeout 1 8 | #log_user 0 9 | 10 | set stty_init "rows 20 cols 100" 11 | 12 | send_user "\nTest Wrap lines wrapping\n" 13 | 14 | set fspec [lindex $argv 0] 15 | spawn ../cligen_file -f $fspec 16 | 17 | send "command\n" 18 | 19 | expect { 20 | timeout { send_user "\nline 9 not received.\n"; exit 1} 21 | "arg 9: line9-abcdefghijklmnopqrstuvw" { send_user "\nline 9 OK.\n";} 22 | } 23 | 24 | expect { 25 | timeout { send_user "\nline 10 received.\n";} 26 | "arg 10: line10-abcdefghijklmnopqrstuvw" { send_user "\nline 10 not expected.\n"; exit 1} 27 | } 28 | 29 | expect { 30 | timeout { send_user "\nMore 1 not received.\n"; exit 1} 31 | -ex "--More--" {send_user "\nMore 1 OK.\n"} 32 | } 33 | 34 | send "\n" 35 | 36 | expect { 37 | timeout { send_user "\nline 10 not received.\n"; exit 1} 38 | "arg 10: line10-abcdefghijklmnopqrstuvw" { send_user "\nline 10 OK.\n"} 39 | } 40 | 41 | expect { 42 | "arg 11: line11-abcdefghijklmnopqrstuvw" { send_user "\nline 11 not expected.\n"; exit 1} 43 | } 44 | 45 | expect { 46 | timeout { send_user "\nMore 2 not received.\n"; exit 1} 47 | -ex "--More--" { send_user "\nMore 2 OK.\n"} 48 | } 49 | 50 | send " " 51 | 52 | expect { 53 | timeout { send_user "\nline 11 not received.\n"; exit 1} 54 | "arg 11: line11-abcdefghijklmnopqrstuvw" {send_user "\nLine 11 OK.\n" } 55 | } 56 | 57 | expect { 58 | timeout { send_user "\nline 19 not received.\n"; exit 1} 59 | "arg 19: line19-abcdefghijklmnopqrstuvw" { send_user "\Line 19 OK.\n" } 60 | } 61 | 62 | expect { 63 | timeout { send_user "\nMore 3 not received.\n"; exit 1} 64 | -ex "--More--" { send_user "\nMore 3 OK.\n" } 65 | } 66 | 67 | send "q" 68 | 69 | expect { 70 | "arg 20: line20-abcdefghijklmnopqrstuvw" { send_user "\nline 20 not expected.\n"; exit 1} 71 | } 72 | 73 | expect { 74 | -ex "--More--" { send_user "\nMore not expected.\n"; exit 1} 75 | } 76 | 77 | send "\d" 78 | close 79 | 80 | send_user "\nTest OK\n" 81 | -------------------------------------------------------------------------------- /test/test_helpstrings.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # CLI helpstring functionality 3 | # Includes: UTF-8, multi-lines, Multi-instance 4 | 5 | # Magic line must be first in script (see README.md) 6 | s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi 7 | 8 | fspec=$dir/spec.cli 9 | 10 | cat > $fspec <("IPv4 address"); 19 | ("Peer group name"); 20 | } 21 | [aaa("Now he sits armed on")|bbb("his Gothic horse")] ccc("his shield strapped"); 22 | [aaa("Now he sits armed on")|bbb("his Gothic horse")] ddd("the prince of the Mærings"); 23 | EOF 24 | 25 | newtest "$cligen_file -f $fspec" 26 | 27 | newtest "multi-line help" 28 | expectpart "$(echo "?" | $cligen_file -f $fspec )" 0 "cli>" "Theodoric the bold" "chief of sea-warriors" "ruled over the shores of the Hreiðsea" 29 | 30 | newtest "same command different help query" 31 | expectpart "$(echo "help ?" | $cligen_file -f $fspec 2>&1)" 0 "cli>" "" "IPv4 address" "Peer group name" 32 | 33 | newtest "same command different help tab" 34 | expectpart "$(echo "help " | $cligen_file -f $fspec 2>&1)" 0 "cli>" "" --not-- "IPv4 address" "Peer group name" 35 | 36 | newtest "cligen instance ?" 37 | ret=$(echo "?" | $cligen_file -f $fspec 2>&1 2>/dev/null) 38 | 39 | newtest "Nr of aaa should be 1" 40 | count=$(echo "$ret" | grep -c "Now he sits armed on") 41 | if [ $count -ne 1 ]; then 42 | err "number of aaa: 1" $count 43 | fi 44 | 45 | newtest "Nr of bbb should be 1" 46 | count=$(echo "$ret" | grep -c "his Gothic horse") 47 | if [ $count -ne 1 ]; then 48 | err "number of bbb: 1" $count 49 | fi 50 | 51 | newtest "Nr of ccc should be 1" 52 | count=$(echo "$ret" | grep -c "his shield strapped") 53 | if [ $count -ne 1 ]; then 54 | err "number of ccc: 1" $count 55 | fi 56 | 57 | newtest "Nr of ddd should be 1" 58 | count=$(echo "$ret" | grep -c "the prince of the Mærings") 59 | if [ $count -ne 1 ]; then 60 | err "number of ddd: 1" $count 61 | fi 62 | 63 | newtest "endtest" 64 | endtest 65 | 66 | unset ret 67 | unset count 68 | 69 | rm -rf $dir 70 | -------------------------------------------------------------------------------- /cligen_getline.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1991, 1992, 1993 by Chris Thewalt (thewalt@ce.berkeley.edu) 3 | * 4 | * Permission to use, copy, modify, and distribute this software 5 | * for any purpose and without fee is hereby granted, provided 6 | * that the above copyright notices appear in all copies and that both the 7 | * copyright notice and this permission notice appear in supporting 8 | * documentation. This software is provided "as is" without express or 9 | * implied warranty. 10 | * 11 | * Thanks to the following people who have provided enhancements and fixes: 12 | * Ron Ueberschaer, Christoph Keller, Scott Schwartz, Steven List, 13 | * DaviD W. Sanderson, Goran Bostrom, Michael Gleason, Glenn Kasten, 14 | * Edin Hodzic, Eric J Bivona, Kai Uwe Rommel, Danny Quah, Ulrich Betzler 15 | */ 16 | 17 | #ifndef CLIGEN_GETLINE_H 18 | #define CLIGEN_GETLINE_H 19 | 20 | /* These declarations are internal to cligen, not part of cligen.h API 21 | */ 22 | 23 | /* 24 | * Types 25 | */ 26 | typedef size_t (*gl_strwidth_proc)(const char *); 27 | 28 | /* 29 | * Prototypes 30 | */ 31 | int gl_eof(void); 32 | void gl_exitchar_add(char c); 33 | void gl_char_init(void); 34 | void gl_char_cleanup(void); 35 | int gl_getline(cligen_handle h, char **buf); /* read a line of input */ 36 | int gl_init(void); 37 | int gl_putc(int c); /* write one char to terminal */ 38 | int gl_getscrolling(void); 39 | void gl_setscrolling(int); 40 | int gl_setwidth(int); /* specify width of screen */ 41 | int gl_getwidth(void); /* get width of screen */ 42 | int gl_utf8_set(int mode); /* set UTF-8 experimental mode */ 43 | int gl_utf8_get(void); /* get UTF-8 mode */ 44 | void gl_strwidth(gl_strwidth_proc); /* to bind gl_strlen */ 45 | void gl_clear_screen(cligen_handle h); /* clear sceen and redraw */ 46 | void gl_redraw(cligen_handle h); /* issue \n and redraw all */ 47 | int gl_regfd(int, cligen_fd_cb_t *, void *); 48 | int gl_unregfd(int); 49 | 50 | extern int (*gl_in_hook)(void *, const char *); 51 | extern int (*gl_out_hook)(void*, const char *); 52 | extern int (*gl_tab_hook)(cligen_handle, int *); 53 | extern cligen_susp_cb_t *gl_susp_hook; 54 | extern cligen_interrupt_cb_t *gl_interrupt_hook; 55 | extern int (*gl_qmark_hook)(cligen_handle, const char *); 56 | 57 | #endif /* CLIGEN_GETLINE_H */ 58 | -------------------------------------------------------------------------------- /cligen_regex.h: -------------------------------------------------------------------------------- 1 | /* 2 | CLI generator regular expressions 3 | 4 | ***** BEGIN LICENSE BLOCK ***** 5 | 6 | Copyright (C) 2001-2022 Olof Hagsand 7 | 8 | This file is part of CLIgen. 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); 11 | you may not use this file except in compliance with the License. 12 | You may obtain a copy of the License at 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | Unless required by applicable law or agreed to in writing, software 17 | distributed under the License is distributed on an "AS IS" BASIS, 18 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | See the License for the specific language governing permissions and 20 | limitations under the License. 21 | 22 | Alternatively, the contents of this file may be used under the terms of 23 | the GNU General Public License Version 2 or later (the "GPL"), 24 | in which case the provisions of the GPL are applicable instead 25 | of those above. If you wish to allow use of your version of this file only 26 | under the terms of the GPL, and not to allow others to 27 | use your version of this file under the terms of Apache License version 2, indicate 28 | your decision by deleting the provisions above and replace them with the 29 | notice and other provisions required by the GPL. If you do not delete 30 | the provisions above, a recipient may use your version of this file under 31 | the terms of any one of the Apache License version 2 or the GPL. 32 | 33 | ***** END LICENSE BLOCK ***** 34 | 35 | This file includes support for regular expressions 36 | */ 37 | 38 | #ifndef _CLIGEN_REGEX_H_ 39 | #define _CLIGEN_REGEX_H_ 40 | 41 | int cligen_regex_posix_compile(const char *regexp, void **recomp); 42 | int cligen_regex_posix_exec(void *recomp, const char *string); 43 | int cligen_regex_posix_free(void *recomp); 44 | int cligen_regex_libxml2_compile(const char *regexp0, void **recomp); 45 | int cligen_regex_libxml2_exec(void *recomp, const char *string0); 46 | int cligen_regex_libxml2_free(void *recomp); 47 | int cligen_regex_compile(cligen_handle h, const char *regexp, void **recomp); 48 | int cligen_regex_exec(cligen_handle h, void *recomp, const char *string); 49 | int cligen_regex_free(cligen_handle h, void *recomp); 50 | int match_regexp(cligen_handle h, const char *string, const char *pattern, int invert); 51 | 52 | #endif /* _CLIGEN_REGEX_H_ */ 53 | -------------------------------------------------------------------------------- /cligen_read.h: -------------------------------------------------------------------------------- 1 | /* 2 | CLI generator readline. Do input processing and matching. 3 | 4 | ***** BEGIN LICENSE BLOCK ***** 5 | 6 | Copyright (C) 2001-2022 Olof Hagsand 7 | 8 | This file is part of CLIgen. 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); 11 | you may not use this file except in compliance with the License. 12 | You may obtain a copy of the License at 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | Unless required by applicable law or agreed to in writing, software 17 | distributed under the License is distributed on an "AS IS" BASIS, 18 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | See the License for the specific language governing permissions and 20 | limitations under the License. 21 | 22 | Alternatively, the contents of this file may be used under the terms of 23 | the GNU General Public License Version 2 or later (the "GPL"), 24 | in which case the provisions of the GPL are applicable instead 25 | of those above. If you wish to allow use of your version of this file only 26 | under the terms of the GPL, and not to allow others to 27 | use your version of this file under the terms of Apache License version 2, indicate 28 | your decision by deleting the provisions above and replace them with the 29 | notice and other provisions required by the GPL. If you do not delete 30 | the provisions above, a recipient may use your version of this file under 31 | the terms of any one of the Apache License version 2 or the GPL. 32 | 33 | ***** END LICENSE BLOCK ***** 34 | 35 | */ 36 | 37 | #ifndef _CLIGEN_READ_H_ 38 | #define _CLIGEN_READ_H_ 39 | 40 | /* 41 | * Constants 42 | */ 43 | /*! Timeout for forked cli output pipe modification function in us */ 44 | #define CLI_PIPE_TIMEOUT_US 1000000 /* 1 s */ 45 | 46 | /* 47 | * Function Prototypes 48 | */ 49 | void cliread_init(cligen_handle h); 50 | int cliread(cligen_handle h, char **stringp); 51 | void cli_trim(char **line, char comment); 52 | int cliread_parse(cligen_handle h, char *string, parse_tree *pt, cg_obj **, 53 | cvec **cvvp, cligen_result *result, char **reason); 54 | int cliread_eval(cligen_handle h, char **line, int *cb_ret, cligen_result *result, char **reason); 55 | int cligen_eval(cligen_handle h, cg_obj *co_match, cvec *cvv); 56 | void cligen_echo_on(void); 57 | void cligen_echo_off(void); 58 | 59 | #endif /* _CLIGEN_READ_H_ */ 60 | -------------------------------------------------------------------------------- /cligen_match.h: -------------------------------------------------------------------------------- 1 | /* 2 | CLI generator match functions, used in runtime checks. 3 | 4 | ***** BEGIN LICENSE BLOCK ***** 5 | 6 | Copyright (C) 2001-2022 Olof Hagsand 7 | 8 | This file is part of CLIgen. 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); 11 | you may not use this file except in compliance with the License. 12 | You may obtain a copy of the License at 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | Unless required by applicable law or agreed to in writing, software 17 | distributed under the License is distributed on an "AS IS" BASIS, 18 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | See the License for the specific language governing permissions and 20 | limitations under the License. 21 | 22 | Alternatively, the contents of this file may be used under the terms of 23 | the GNU General Public License Version 2 or later (the "GPL"), 24 | in which case the provisions of the GPL are applicable instead 25 | of those above. If you wish to allow use of your version of this file only 26 | under the terms of the GPL, and not to allow others to 27 | use your version of this file under the terms of Apache License version 2, indicate 28 | your decision by deleting the provisions above and replace them with the 29 | notice and other provisions required by the GPL. If you do not delete 30 | the provisions above, a recipient may use your version of this file under 31 | the terms of any one of the Apache License version 2 or the GPL. 32 | 33 | ***** END LICENSE BLOCK ***** 34 | 35 | */ 36 | 37 | #ifndef _CLIGEN_MATCH_H 38 | #define _CLIGEN_MATCH_H 39 | 40 | /* Number of allowed matchings */ 41 | #define MATCHVECTORLEN 1024 42 | 43 | /* 44 | * Function Prototypes 45 | */ 46 | int match_pattern(cligen_handle h, cvec *cvt, cvec *cvr, 47 | parse_tree *pt, 48 | int best, 49 | cvec *cvv, 50 | match_result **mrp); 51 | 52 | int match_pattern_exact(cligen_handle h, cvec *cvt, cvec *cvr, 53 | parse_tree *pt, 54 | cvec *cvv, 55 | cg_obj **match_obj, 56 | cligen_result *result, 57 | char **reasonp); 58 | int cligen_cvv_levels(cvec *cvv); 59 | int match_complete(cligen_handle h, parse_tree *pt, 60 | char **stringp, size_t *slen, cvec *cvec); 61 | 62 | #endif /* _CLIGEN_MATCH_H */ 63 | -------------------------------------------------------------------------------- /test/test_pipe.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Output pipe modifier tests 3 | # Assume pipe_shell_fn and grep_fn in cligen_file.c 4 | 5 | # Magic line must be first in script (see README.md) 6 | s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi 7 | 8 | fspec=$dir/spec.cli 9 | 10 | lines='"line6 def", "line7 def", "line1 abc", "line2 abc", "line3 abc", "line4 abc", "line5 def"' 11 | 12 | cat > $fspec <, pipe_shell_fn("grep -e", "arg"); 32 | tail, pipe_shell_fn("tail -3"); 33 | count, pipe_shell_fn("wc -l"); 34 | cat, pipe_shell_fn("cat"); 35 | } 36 | 37 | treename="treeref"; 38 | pipetree="|mypipe"; 39 | extra, output_fn($lines); 40 | EOF 41 | 42 | # Run pipe commands 43 | # Parameters: 44 | # 1: Top-level command 45 | # 2: Direct command (ie no pipe) 46 | function runtest() 47 | { 48 | cmd=$1 49 | direct=$2 50 | 51 | if $direct; then 52 | newtest "base" 53 | expectpart "$(echo "$cmd" | $cligen_file -f $fspec)" 0 "line1 abc" "line5 def" 54 | fi 55 | 56 | newtest "grep" 57 | expectpart "$(echo "$cmd \| grep abc" | $cligen_file -f $fspec)" 0 "line1 abc" --not-- "line6 def" 58 | 59 | newtest "tail" 60 | expectpart "$(echo "$cmd \| tail" | $cligen_file -f $fspec)" 0 "line3 abc" --not-- "line2 abc" 61 | 62 | newtest "count" 63 | expectpart "$(echo "$cmd \| count" | $cligen_file -f $fspec)" 0 7 64 | 65 | newtest "skip space: count" 66 | expectpart "$(echo "$cmd\|count" | $cligen_file -f $fspec)" 0 7 67 | 68 | newtest "double: cat | cat expect fail" 69 | expectpart "$(echo "$cmd \| cat \| cat" | $cligen_file -f $fspec)" 0 "Unknown command" 70 | } 71 | 72 | newtest "$cligen_file -f $fspec" 73 | 74 | newtest "Implicit output pipe" 75 | runtest set1 true 76 | 77 | newtest "Explicit output pipe" 78 | runtest set2 true 79 | 80 | newtest "Explicit no direct" 81 | runtest set3 false 82 | 83 | newtest "Implicit via treeref" 84 | runtest "set4 extra" true 85 | 86 | newtest "endtest" 87 | endtest 88 | 89 | rm -rf $dir 90 | 91 | -------------------------------------------------------------------------------- /test/test_mode.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # CLI tree mode 3 | 4 | # Magic line must be first in script (see README.md) 5 | s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi 6 | 7 | fspec=$dir/spec.cli 8 | fin=$dir/in 9 | 10 | cat > $fspec <; { 25 | d; 26 | } 27 | c; 28 | } 29 | EOF 30 | 31 | newtest "$cligen_tutorial -f $fspec" # To bind the cligen_wp_* functions 32 | 33 | function testrun() 34 | { 35 | options="-q -f $fspec" # default is full copies 36 | 37 | newtest "cligen show top tree" 38 | expectpart "$(echo "show" | $cligen_tutorial ${options} 2>&1)" 0 "a;{" "b ;{" "d;" "c;" 39 | 40 | cat < $fin 41 | up 42 | show 43 | EOF 44 | newtest "cligen up" 45 | expectpart "$(cat $fin | $cligen_tutorial ${options} 2>&1)" 0 "a;{" "b ;{" "d;" "c;" 46 | 47 | cat < $fin 48 | edit a 49 | show 50 | EOF 51 | newtest "cligen edit a" 52 | expectpart "$(cat $fin | $cligen_tutorial ${options} 2>&1)" 0 "b ;{" "d;" "c;" --not-- "a;{" 53 | 54 | cat < $fin 55 | edit a 56 | edit b 23 57 | show 58 | EOF 59 | 60 | newtest "cligen edit a b " 61 | expectpart "$(cat $fin | $cligen_tutorial ${options} 2>&1)" 0 "d;" --not-- "b ;{" "c;" "a;{" 62 | 63 | cat < $fin 64 | edit a b 23 65 | up 66 | show 67 | EOF 68 | 69 | newtest "cligen edit a b up" 70 | expectpart "$(cat $fin | $cligen_tutorial ${options} 2>&1)" 0 ";{" "d;" --not-- "b ;{" "c;" "a;{" 71 | 72 | cat < $fin 73 | edit a b 23 74 | up 75 | up 76 | show 77 | EOF 78 | 79 | newtest "cligen edit a b up up" 80 | expectpart "$(cat $fin | $cligen_tutorial ${options} 2>&1)" 0 "b ;{" "c;" "d;" --not-- "a;{" 81 | 82 | cat < $fin 83 | edit a b 23 84 | top 85 | show 86 | EOF 87 | 88 | newtest "cligen edit a b top" 89 | expectpart "$(cat $fin | $cligen_tutorial ${options} 2>&1)" 0 "a;{" "b ;{" "d;" "c;" 90 | } 91 | 92 | newtest "Run mode tests" 93 | testrun 94 | 95 | newtest "endtest" 96 | endtest 97 | 98 | rm -rf $dir 99 | 100 | -------------------------------------------------------------------------------- /cligen_history.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Code in this file is based on: 3 | * 4 | * Copyright (C) 1991, 1992, 1993 by Chris Thewalt (thewalt@ce.berkeley.edu) 5 | * 6 | * Permission to use, copy, modify, and distribute this software 7 | * for any purpose and without fee is hereby granted, provided 8 | * that the above copyright notices appear in all copies and that both the 9 | * copyright notice and this permission notice appear in supporting 10 | * documentation. This software is provided "as is" without express or 11 | * implied warranty. 12 | * 13 | * Thanks to the following people who have provided enhancements and fixes: 14 | * Ron Ueberschaer, Christoph Keller, Scott Schwartz, Steven List, 15 | * DaviD W. Sanderson, Goran Bostrom, Michael Gleason, Glenn Kasten, 16 | * Edin Hodzic, Eric J Bivona, Kai Uwe Rommel, Danny Quah, Ulrich Betzler 17 | 18 | * Modifications are under: 19 | ***** BEGIN LICENSE BLOCK ***** 20 | 21 | Copyright (C) 2001-2022 Olof Hagsand 22 | 23 | This file is part of CLIgen. 24 | 25 | Licensed under the Apache License, Version 2.0 (the "License"); 26 | you may not use this file except in compliance with the License. 27 | You may obtain a copy of the License at 28 | 29 | http://www.apache.org/licenses/LICENSE-2.0 30 | 31 | Unless required by applicable law or agreed to in writing, software 32 | distributed under the License is distributed on an "AS IS" BASIS, 33 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 34 | See the License for the specific language governing permissions and 35 | limitations under the License. 36 | 37 | Alternatively, the contents of this file may be used under the terms of 38 | the GNU General Public License Version 2 or later (the "GPL"), 39 | in which case the provisions of the GPL are applicable instead 40 | of those above. If you wish to allow use of your version of this file only 41 | under the terms of the GPL, and not to allow others to 42 | use your version of this file under the terms of Apache License version 2, indicate 43 | your decision by deleting the provisions above and replace them with the 44 | notice and other provisions required by the GPL. If you do not delete 45 | the provisions above, a recipient may use your version of this file under 46 | the terms of any one of the Apache License version 2 or the GPL. 47 | 48 | ***** END LICENSE BLOCK ***** 49 | 50 | */ 51 | 52 | #ifndef CLIGEN_HISTORY_H 53 | #define CLIGEN_HISTORY_H 54 | 55 | /* 56 | * Prototypes 57 | */ 58 | int cligen_hist_init(cligen_handle h, int lines); 59 | int cligen_hist_file_load(cligen_handle h, FILE *f); 60 | int cligen_hist_file_save(cligen_handle h, FILE *f); 61 | 62 | #endif /* CLIGEN_HISTORY_H */ 63 | -------------------------------------------------------------------------------- /cligen_config.h.in: -------------------------------------------------------------------------------- 1 | /* cligen_config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Enable BSD select semantics allowing multiple input file descriptors to be 4 | enabled at once, Not just stdin. Each extra fd is registered with 5 | cligen_regfd() */ 6 | #undef CLIGEN_REGFD 7 | 8 | /* Experimental CLIGEN sub-modes */ 9 | #undef CLIGEN_SUBMODE 10 | 11 | /* Define to 1 if you have the header file. */ 12 | #undef HAVE_INTTYPES_H 13 | 14 | /* Define to 1 if you have the `socket' library (-lsocket). */ 15 | #undef HAVE_LIBSOCKET 16 | 17 | /* Define to 1 if you have the `xml2' library (-lxml2). */ 18 | #undef HAVE_LIBXML2 19 | 20 | /* Define to 1 if you have the header file. */ 21 | #undef HAVE_LIBXML_XMLREGEXP_H 22 | 23 | /* Define to 1 if you have the header file. */ 24 | #undef HAVE_STDINT_H 25 | 26 | /* Define to 1 if you have the header file. */ 27 | #undef HAVE_STDIO_H 28 | 29 | /* Define to 1 if you have the header file. */ 30 | #undef HAVE_STDLIB_H 31 | 32 | /* Define to 1 if you have the header file. */ 33 | #undef HAVE_STRINGS_H 34 | 35 | /* Define to 1 if you have the header file. */ 36 | #undef HAVE_STRING_H 37 | 38 | /* Define to 1 if you have the `strsep' function. */ 39 | #undef HAVE_STRSEP 40 | 41 | /* Define to 1 if you have the `strverscmp' function. */ 42 | #undef HAVE_STRVERSCMP 43 | 44 | /* Define to 1 if you have the header file. */ 45 | #undef HAVE_SYS_STAT_H 46 | 47 | /* Define to 1 if you have the header file. */ 48 | #undef HAVE_SYS_TYPES_H 49 | 50 | /* Define to 1 if you have the header file. */ 51 | #undef HAVE_TERMIOS_H 52 | 53 | /* Define to 1 if you have the header file. */ 54 | #undef HAVE_UNISTD_H 55 | 56 | /* Define to the address where bug reports for this package should be sent. */ 57 | #undef PACKAGE_BUGREPORT 58 | 59 | /* Define to the full name of this package. */ 60 | #undef PACKAGE_NAME 61 | 62 | /* Define to the full name and version of this package. */ 63 | #undef PACKAGE_STRING 64 | 65 | /* Define to the one symbol short name of this package. */ 66 | #undef PACKAGE_TARNAME 67 | 68 | /* Define to the home page for this package. */ 69 | #undef PACKAGE_URL 70 | 71 | /* Define to the version of this package. */ 72 | #undef PACKAGE_VERSION 73 | 74 | /* Define to 1 if all of the C90 standard headers exist (not just the ones 75 | required in a freestanding environment). This macro is provided for 76 | backward compatibility; new code need not use it. */ 77 | #undef STDC_HEADERS 78 | 79 | /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a 80 | `char[]'. */ 81 | #undef YYTEXT_POINTER 82 | 83 | #include 84 | -------------------------------------------------------------------------------- /cligen_expand.h: -------------------------------------------------------------------------------- 1 | /* 2 | CLI generator. Take idl as input and generate a tree for use in cli. 3 | 4 | ***** BEGIN LICENSE BLOCK ***** 5 | 6 | Copyright (C) 2001-2022 Olof Hagsand 7 | 8 | This file is part of CLIgen. 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); 11 | you may not use this file except in compliance with the License. 12 | You may obtain a copy of the License at 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | Unless required by applicable law or agreed to in writing, software 17 | distributed under the License is distributed on an "AS IS" BASIS, 18 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | See the License for the specific language governing permissions and 20 | limitations under the License. 21 | 22 | Alternatively, the contents of this file may be used under the terms of 23 | the GNU General Public License Version 2 or later (the "GPL"), 24 | in which case the provisions of the GPL are applicable instead 25 | of those above. If you wish to allow use of your version of this file only 26 | under the terms of the GPL, and not to allow others to 27 | use your version of this file under the terms of Apache License version 2, indicate 28 | your decision by deleting the provisions above and replace them with the 29 | notice and other provisions required by the GPL. If you do not delete 30 | the provisions above, a recipient may use your version of this file under 31 | the terms of any one of the Apache License version 2 or the GPL. 32 | 33 | ***** END LICENSE BLOCK ***** 34 | 35 | */ 36 | 37 | #ifndef _CLIGEN_EXPAND_H_ 38 | #define _CLIGEN_EXPAND_H_ 39 | 40 | /* 41 | * Constants 42 | */ 43 | 44 | /*! Local flag beginning with this prefix can be used as filter statements in tree references 45 | * 46 | * Example: 47 | * @subtree, @remove:local # Filter out all statements with flag "local" 48 | * treename="subtree"; 49 | * xx; 50 | * yy, local; # Filter this 51 | */ 52 | #define CLIGEN_REF_REMOVE "@remove:" 53 | 54 | /* 55 | * Types 56 | */ 57 | /* Here we should have expand_cb but it is in cligen_object.h */ 58 | 59 | /* 60 | * Prototypes 61 | */ 62 | int cligen_escape_need(const char *s); 63 | char *cligen_escape_do(const char *s); 64 | int co_isfilter(cvec *cvv_filter, const char *label); 65 | char *pt_local_pipe(parse_tree *pt); 66 | int pt_expand(cligen_handle h, cg_obj *co, parse_tree *pt, cvec *cvt, cvec *cvv, 67 | int hide, int expandvar, cg_callback *callbacks, 68 | cg_obj *co_pipe, parse_tree *ptn); 69 | int pt_expand_cleanup(cligen_handle h, parse_tree *pt); 70 | int reference_path_match(cg_obj *co1, parse_tree *pt0, cg_obj **co0p); 71 | 72 | #endif /* _CLIGEN_EXPAND_H_ */ 73 | 74 | -------------------------------------------------------------------------------- /cligen_buf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ***** BEGIN LICENSE BLOCK ***** 3 | 4 | Copyright (C) 2001-2022 Olof Hagsand 5 | 6 | This file is part of CLIgen. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | Alternatively, the contents of this file may be used under the terms of 21 | the GNU General Public License Version 2 or later (the "GPL"), 22 | in which case the provisions of the GPL are applicable instead 23 | of those above. If you wish to allow use of your version of this file only 24 | under the terms of the GPL, and not to allow others to 25 | use your version of this file under the terms of Apache License version 2, indicate 26 | your decision by deleting the provisions above and replace them with the 27 | notice and other provisions required by the GPL. If you do not delete 28 | the provisions above, a recipient may use your version of this file under 29 | the terms of any one of the Apache License version 2 or the GPL. 30 | 31 | ***** END LICENSE BLOCK ***** 32 | 33 | * 34 | * 35 | * CLIgen dynamic buffers 36 | * @code 37 | * cbuf *cb; 38 | * if ((cb = cbuf_new()) == NULL) 39 | * err(); 40 | * cprintf(cb, "%d %s", 43, "go"); 41 | * if (write(f, cbuf_get(cb), cbuf_len(cb)) < 0) 42 | * err(); 43 | * cbuf_free(cb); 44 | * @endcode 45 | */ 46 | 47 | #ifndef _CLIGEN_BUF_H 48 | #define _CLIGEN_BUF_H 49 | 50 | #include 51 | 52 | /* 53 | * Types 54 | */ 55 | typedef struct cbuf cbuf; /* cligen buffer type is fully defined in c-file */ 56 | 57 | /* 58 | * Prototypes 59 | */ 60 | int cbuf_alloc_get(size_t *start, size_t *threshold); 61 | int cbuf_alloc_set(size_t start, size_t threshold); 62 | cbuf *cbuf_new(void); 63 | cbuf *cbuf_new_alloc(size_t sz); 64 | void cbuf_free(cbuf *cb); 65 | char *cbuf_get(cbuf *cb); 66 | size_t cbuf_len(cbuf *cb); 67 | size_t cbuf_buflen(cbuf *cb); 68 | int cprintf(cbuf *cb, const char *format, ...) __attribute__ ((format (printf, 2, 3))); 69 | int vcprintf(cbuf *cb, const char *format, va_list ap); 70 | void cbuf_reset(cbuf *cb); 71 | int cbuf_append(cbuf *cb, int c); 72 | int cbuf_append_str(cbuf *cb, const char *str); 73 | int cbuf_append_buf(cbuf *cb, void *src, size_t n); 74 | int cbuf_trunc(cbuf *cb, size_t i); 75 | 76 | #endif /* _CLIGEN_BUF_H */ 77 | -------------------------------------------------------------------------------- /cligen_history_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Code in this file is based on: 3 | * 4 | * Copyright (C) 1991, 1992, 1993 by Chris Thewalt (thewalt@ce.berkeley.edu) 5 | * 6 | * Permission to use, copy, modify, and distribute this software 7 | * for any purpose and without fee is hereby granted, provided 8 | * that the above copyright notices appear in all copies and that both the 9 | * copyright notice and this permission notice appear in supporting 10 | * documentation. This software is provided "as is" without express or 11 | * implied warranty. 12 | * 13 | * Thanks to the following people who have provided enhancements and fixes: 14 | * Ron Ueberschaer, Christoph Keller, Scott Schwartz, Steven List, 15 | * DaviD W. Sanderson, Goran Bostrom, Michael Gleason, Glenn Kasten, 16 | * Edin Hodzic, Eric J Bivona, Kai Uwe Rommel, Danny Quah, Ulrich Betzler 17 | 18 | * Modifications are under: 19 | ***** BEGIN LICENSE BLOCK ***** 20 | 21 | Copyright (C) 2001-2022 Olof Hagsand 22 | 23 | This file is part of CLIgen. 24 | 25 | Licensed under the Apache License, Version 2.0 (the "License"); 26 | you may not use this file except in compliance with the License. 27 | You may obtain a copy of the License at 28 | 29 | http://www.apache.org/licenses/LICENSE-2.0 30 | 31 | Unless required by applicable law or agreed to in writing, software 32 | distributed under the License is distributed on an "AS IS" BASIS, 33 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 34 | See the License for the specific language governing permissions and 35 | limitations under the License. 36 | 37 | Alternatively, the contents of this file may be used under the terms of 38 | the GNU General Public License Version 2 or later (the "GPL"), 39 | in which case the provisions of the GPL are applicable instead 40 | of those above. If you wish to allow use of your version of this file only 41 | under the terms of the GPL, and not to allow others to 42 | use your version of this file under the terms of Apache License version 2, indicate 43 | your decision by deleting the provisions above and replace them with the 44 | notice and other provisions required by the GPL. If you do not delete 45 | the provisions above, a recipient may use your version of this file under 46 | the terms of any one of the Apache License version 2 or the GPL. 47 | 48 | ***** END LICENSE BLOCK ***** 49 | 50 | */ 51 | 52 | #ifndef CLIGEN_HISTORY_INTERNAL_H 53 | #define CLIGEN_HISTORY_INTERNAL_H 54 | 55 | /* 56 | * Prototypes 57 | */ 58 | int hist_add(cligen_handle h, const char *buf); 59 | int hist_exit(cligen_handle h); 60 | char *hist_next(cligen_handle h); 61 | char *hist_prev(cligen_handle h); 62 | int hist_pos_set(cligen_handle h, int pos); 63 | int hist_pos(cligen_handle h); 64 | int hist_last_get(cligen_handle h); 65 | int hist_copy_pos(cligen_handle h); 66 | int hist_copy_prev(cligen_handle h); 67 | int hist_copy_next(cligen_handle h); 68 | 69 | #endif /* CLIGEN_HISTORY_INTERNAL_H */ 70 | -------------------------------------------------------------------------------- /cligen.h: -------------------------------------------------------------------------------- 1 | /* 2 | CLIgen is a CLI generator. 3 | 4 | ***** BEGIN LICENSE BLOCK ***** 5 | 6 | Copyright (C) 2001-2022 Olof Hagsand 7 | 8 | This file is part of CLIgen. 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); 11 | you may not use this file except in compliance with the License. 12 | You may obtain a copy of the License at 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | Unless required by applicable law or agreed to in writing, software 17 | distributed under the License is distributed on an "AS IS" BASIS, 18 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | See the License for the specific language governing permissions and 20 | limitations under the License. 21 | 22 | Alternatively, the contents of this file may be used under the terms of 23 | the GNU General Public License Version 2 or later (the "GPL"), 24 | in which case the provisions of the GPL are applicable instead 25 | of those above. If you wish to allow use of your version of this file only 26 | under the terms of the GPL, and not to allow others to 27 | use your version of this file under the terms of Apache License version 2, indicate 28 | your decision by deleting the provisions above and replace them with the 29 | notice and other provisions required by the GPL. If you do not delete 30 | the provisions above, a recipient may use your version of this file under 31 | the terms of any one of the Apache License version 2 or the GPL. 32 | 33 | ***** END LICENSE BLOCK ***** 34 | 35 | */ 36 | 37 | /* 38 | You include cligen.h which includes the other cligen include files for you. 39 | All cligen include files are placed in the sub-directory cligen/cligen*.h. 40 | */ 41 | #include 42 | #include 43 | 44 | /* CLIgen handle for external API. See cligen_config.h for internal functions. */ 45 | #ifndef _CLIGEN_H_ 46 | #define _CLIGEN_H_ 47 | #if 1 /* SANITY CHECK */ 48 | typedef struct {int a;} *cligen_handle; 49 | #else 50 | typedef void *cligen_handle; /* API */ 51 | #endif 52 | #endif /* _CLIGEN_H_ */ 53 | 54 | #ifdef __cplusplus 55 | extern "C" { 56 | #endif 57 | 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | #include 73 | #include 74 | #include 75 | 76 | #ifdef __cplusplus 77 | } /* extern "C" */ 78 | #endif 79 | 80 | /* 81 | * Global variables generated by Makefile 82 | */ 83 | extern const char CLIGEN_BUILDSTR[]; 84 | extern const char CLIGEN_VERSION[]; 85 | 86 | -------------------------------------------------------------------------------- /cligen_io.h: -------------------------------------------------------------------------------- 1 | /* 2 | CLI generator input/output support functions. 3 | 4 | ***** BEGIN LICENSE 5 | 6 | Copyright (C) 2001-2022 Olof Hagsand 7 | 8 | This file is part of CLIgen. 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); 11 | you may not use this file except in compliance with the License. 12 | You may obtain a copy of the License at 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | Unless required by applicable law or agreed to in writing, software 17 | distributed under the License is distributed on an "AS IS" BASIS, 18 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | See the License for the specific language governing permissions and 20 | limitations under the License. 21 | 22 | Alternatively, the contents of this file may be used under the terms of 23 | the GNU General Public License Version 2 or later (the "GPL"), 24 | in which case the provisions of the GPL are applicable instead 25 | of those above. If you wish to allow use of your version of this file only 26 | under the terms of the GPL, and not to allow others to 27 | use your version of this file under the terms of Apache License version 2, indicate 28 | your decision by deleting the provisions above and replace them with the 29 | notice and other provisions required by the GPL. If you do not delete 30 | the provisions above, a recipient may use your version of this file under 31 | the terms of any one of the Apache License version 2 or the GPL. 32 | 33 | * ***** END LICENSE BLOCK ***** * 34 | */ 35 | 36 | #ifndef _CLIGEN_IO_H_ 37 | #define _CLIGEN_IO_H_ 38 | 39 | /* 40 | * Constants 41 | */ 42 | 43 | #define COLUMN_MIN_WIDTH 21 /* For column formatting how many chars minimum 44 | for command/var */ 45 | 46 | /* 47 | * Types 48 | */ 49 | /* Struct for printing command and help */ 50 | struct cligen_help{ 51 | char *ch_cmd; /* Malloced string */ 52 | cvec *ch_helpvec; 53 | }; 54 | 55 | /* CLIgen event register callback type */ 56 | typedef int (cligen_fd_cb_t)(int, void*); 57 | 58 | /* 59 | * Prototypes 60 | */ 61 | int cli_pipe_output_socket_get(int *s); 62 | int cli_pipe_output_socket_set(int s); 63 | int cli_output_reset(void); 64 | int cli_output_status(void); 65 | int cligen_output(FILE *f, const char *templ, ... ) __attribute__ ((format (printf, 2, 3))); 66 | int cligen_output_basic(FILE *f, const char *inbuf, size_t inbuflen); 67 | int cligen_regfd(int fd, cligen_fd_cb_t *cb, void *arg); 68 | int cligen_unregfd(int fd); 69 | void cligen_redraw(cligen_handle h); 70 | int cligen_susp_hook(cligen_handle h, cligen_susp_cb_t *fn); 71 | int cligen_interrupt_hook(cligen_handle h, cligen_interrupt_cb_t *fn); 72 | void cligen_exitchar_add(cligen_handle h, char c); 73 | int cligen_help_eq(struct cligen_help *ch0, struct cligen_help *ch1, int help); 74 | int cligen_help_clear(struct cligen_help *ch0); 75 | int print_help_lines(cligen_handle h, FILE *fout, parse_tree *ptmatch); 76 | int cligen_help(cligen_handle h, FILE *f, parse_tree *pt); 77 | 78 | #endif /* _CLIGEN_IO_H_ */ 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CLIgen 2 | 3 | [![Build Status](https://github.com/clicon/cligen/actions/workflows/ci.yml/badge.svg)](https://github.com/clicon/cligen/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/clicon/cligen/branch/master/graph/badge.svg?token=6HXN51SARU)](https://codecov.io/gh/clicon/cligen) Coverity Scan Build Status 4 | 5 | CLIgen is a Command-Line Interface generator. 6 | 7 | Well, actually it is not really a generator, since it does 8 | not _generate_ code for CLI:s. Instead, it builds and interprets 9 | datastructures (a parse-tree) which a library (libcligen) interprets 10 | in runtime. It is fast and efficient and helps you develop CLI:s 11 | easier. You enter a CLI syntax in a text file, and 12 | write callback functions in C. The callback functions add the semantics, that is, what the 13 | commands in the CLI are supposed to do. 14 | 15 | The main documentation is the [cligen tutorial](cligen_tutorial.pdf) 16 | which is usually kept up-to-date and is probably the best way to 17 | understand CLIgen. 18 | 19 | Some background material can be found on the [CLIgen project page](https://www.cligen.se). 20 | 21 | CLIgen is _not_ a system in itself, you need to build your own 22 | 'backend'. There is another co-project: 'clixon' which is 23 | a whole system where you load dynamic frontend and backend 24 | modules. See [CLIXON project page](https://www.clicon.org) and [CLIXON 25 | github](https://github.com/clicon/clixon). Clixon provides a 26 | system with embedded database, commit semantics, YANG and NETCONF 27 | interface, etc. CLIgen is a part of clixon but can be used by itself. 28 | 29 | The source code here is built and installed using: 30 | ``` 31 | configure; 32 | make; 33 | sudo make install. 34 | ``` 35 | 36 | The source builds a single library. If you build applications, you should include cligen.h and link with the library. 37 | 38 | There are several example applications: 39 | * cligen_hello Simplest possible. Just builds a 'hello world' greeting by in-line C 40 | * cligen_file Read a syntax specification from file. You must supply the file. 41 | * cligen_tutorial Samples of techniques used in [cligen_tutorial.pdf](cligen_tutorial.pdf) 42 | 43 | See also [Changelog](CHANGELOG.md). 44 | 45 | For building the C reference documentation using doxygen, do: `make doc` and place your browser at `doc/index.html`. 46 | 47 | CLIgen is dual license. Either Apache License, Version 2.0 or GNU 48 | General Public License Version 2. You choose. 49 | 50 | I can be found at olof@hagsand.se. 51 | 52 | ## getline 53 | 54 | CLIgen uses getline with the following copyright: 55 | 56 | Copyright (C) 1991, 1992, 1993 by Chris Thewalt (thewalt@ce.berkeley.edu) 57 | 58 | Permission to use, copy, modify, and distribute this software 59 | for any purpose and without fee is hereby granted, provided 60 | that the above copyright notices appear in all copies and that both the 61 | copyright notice and this permission notice appear in supporting 62 | documentation. This software is provided "as is" without express or 63 | implied warranty. 64 | -------------------------------------------------------------------------------- /cligen_result.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ***** BEGIN LICENSE BLOCK ***** 4 | 5 | Copyright (C) 2001-2022 Olof Hagsand 6 | 7 | This file is part of CLIgen. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | Alternatively, the contents of this file may be used under the terms of 22 | the GNU General Public License Version 2 or later (the "GPL"), 23 | in which case the provisions of the GPL are applicable instead 24 | of those above. If you wish to allow use of your version of this file only 25 | under the terms of the GPL, and not to allow others to 26 | use your version of this file under the terms of Apache License version 2, indicate 27 | your decision by deleting the provisions above and replace them with the 28 | notice and other provisions required by the GPL. If you do not delete 29 | the provisions above, a recipient may use your version of this file under 30 | the terms of any one of the Apache License version 2 or the GPL. 31 | 32 | ***** END LICENSE BLOCK ***** 33 | 34 | * Result generated when matching and used inyternally in cligen 35 | * This include file is used internally in cligen, not part of API 36 | * The C struct is not exposed outside the .c file 37 | */ 38 | 39 | #ifndef _CLIGEN_RESULT_H 40 | #define _CLIGEN_RESULT_H 41 | 42 | /* 43 | * Types 44 | */ 45 | enum cligen_result{ 46 | CG_EOF = -2, 47 | CG_ERROR = -1, 48 | CG_NOMATCH = 0, 49 | CG_MATCH = 1, 50 | CG_MULTIPLE = 2, 51 | }; 52 | typedef enum cligen_result cligen_result; 53 | 54 | /* see cligen_match_result.c for struct declaration */ 55 | typedef struct match_result match_result; 56 | 57 | /* 58 | * Prototypes 59 | */ 60 | int mr_pt_len_get(match_result *mr); 61 | int mr_pt_reset(match_result *mr); 62 | int mr_pt_trunc(match_result *mr, int len); 63 | int mr_pt_append(match_result *mr, cg_obj *co, char *token); 64 | cg_obj *mr_pt_i_get(match_result *mr, int i); 65 | parse_tree *mr_pt_get(match_result *mr); 66 | char *mr_reason_get(match_result *mr); 67 | int mr_reason_set(match_result *mr, char *reason); 68 | int mr_level_get(match_result *mr); 69 | int mr_level_set(match_result *mr, int level); 70 | uint32_t mr_pref_get(match_result *mr); 71 | int mr_pref_set(match_result *mr, uint32_t pref); 72 | char *mr_token_get(match_result *mr); 73 | int mr_last_get(match_result *mr); 74 | int mr_last_set(match_result *mr); 75 | int mr_mv_reason(match_result *from, match_result *to); 76 | match_result *mr_new(void); 77 | int mr_free(match_result *mr); 78 | cligen_result mr2result(match_result *mr); 79 | int mr_flags_set_co_match(match_result *mr, cg_obj *co); 80 | 81 | #endif /* _CLIGEN_RESULT_H */ 82 | -------------------------------------------------------------------------------- /cligen_cvec.h: -------------------------------------------------------------------------------- 1 | /* 2 | ***** BEGIN LICENSE BLOCK ***** 3 | 4 | Copyright (C) 2001-2022 Olof Hagsand 5 | 6 | This file is part of CLIgen. 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | 20 | Alternatively, the contents of this file may be used under the terms of 21 | the GNU General Public License Version 2 or later (the "GPL"), 22 | in which case the provisions of the GPL are applicable instead 23 | of those above. If you wish to allow use of your version of this file only 24 | under the terms of the GPL, and not to allow others to 25 | use your version of this file under the terms of Apache License version 2, indicate 26 | your decision by deleting the provisions above and replace them with the 27 | notice and other provisions required by the GPL. If you do not delete 28 | the provisions above, a recipient may use your version of this file under 29 | the terms of any one of the Apache License version 2 or the GPL. 30 | 31 | ***** END LICENSE BLOCK ***** 32 | 33 | CLIgen variable vectors - cvec 34 | */ 35 | 36 | #ifndef _CLIGEN_CVEC_H_ 37 | #define _CLIGEN_CVEC_H_ 38 | 39 | /* 40 | * CLIgen variable record that encapsulates parsed variable vectors, etc. 41 | * Never use these fields directly. 42 | * Defined internally in cligen_cvec.c 43 | */ 44 | typedef struct cvec cvec; 45 | 46 | /* 47 | * Prototypes 48 | */ 49 | cvec *cvec_new(int len); 50 | cvec *cvec_from_var(cg_var *cv); 51 | int cvec_free(cvec *vr); 52 | int cvec_init(cvec *vr, int len); 53 | int cvec_reset(cvec *vr); 54 | int cvec_len(cvec *vr); 55 | cg_var *cvec_i(cvec *vr, int i); 56 | char *cvec_i_str(cvec *cvv, int i); 57 | cg_var *cvec_next(cvec *vr, cg_var *cv0); 58 | cg_var *cvec_add(cvec *vr, enum cv_type type); 59 | cg_var *cvec_append_var(cvec *cvv, cg_var *var); 60 | int cvec_del(cvec *vr, cg_var *del); 61 | int cvec_del_i(cvec *vr, int ix); 62 | cg_var *cvec_each(cvec *vr, cg_var *prev); 63 | cg_var *cvec_each1(cvec *vr, cg_var *prev); 64 | cvec *cvec_dup(cvec *old); 65 | cvec *cvec_start(const char *cmd); 66 | int cvec_print(FILE *f, cvec *vr); 67 | int cvec2cbuf(cbuf *cb, cvec *cvv); 68 | cg_var *cvec_find(cvec *vr, const char *name); 69 | cg_var *cvec_find_keyword(cvec *vr, const char *name); 70 | cg_var *cvec_find_var(cvec *vr, const char *name); 71 | char *cvec_find_str(cvec *vr, const char *name); 72 | char *cvec_name_get(cvec *vr); 73 | char *cvec_name_set(cvec *vr, const char *name); 74 | size_t cvec_size(cvec *cvv); 75 | int cligen_txt2cvv(const char *str, cvec **cvp); 76 | int cligen_str2cvv(const char *string, cvec **cvp, cvec **cvr); 77 | int cvec_expand_first(cvec *cvv); 78 | int cvec_exclude_keys(cvec *cvv); 79 | 80 | #endif /* _CLIGEN_CVEC_H_ */ 81 | -------------------------------------------------------------------------------- /test/test_getline.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # CLI getline tests 3 | # go through all control 4 | 5 | # Magic line must be first in script (see README.md) 6 | s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi 7 | 8 | fspec=$dir/spec.cli 9 | 10 | cat > $fspec <&1)" 0 "chief of sea-warriors" 24 | 25 | newtest "^h" 26 | expectpart "$(echo -n "ruled over the" | $cligen_file -f $fspec 2>&1)" 0 "ruled over" 27 | 28 | newtest "b,^f" 29 | expectpart "$(echo -n "ruled over theb" | $cligen_file -f $fspec 2>&1)" 0 "ruled over the" 30 | 31 | newtest "f,^f" 32 | expectpart "$(echo -n "ruled over thebf" | $cligen_file -f $fspec 2>&1)" 0 "ruled over the" 33 | 34 | # up 35 | newtest "^p" 36 | expectpart "$(echo -n "ruled  over the" | $cligen_file -f $fspec 2>&1)" 0 "ruled over the" 37 | 38 | newtest "ANSI arrows up" 39 | expectpart "$(echo -n "ruled  over the" | $cligen_file -f $fspec 2>&1)" 0 "ruled over the" 40 | 41 | # down 42 | newtest "^pn" 43 | expectpart "$(echo -n "ruled Theo   " | $cligen_file -f $fspec)" 0 "Theodoric the bold " 44 | 45 | newtest "ANSI arrows up/down" 46 | expectpart "$(echo -n "ruled Theo   " | $cligen_file -f $fspec)" 0 "Theodoric the bold " 47 | 48 | newtest "^ut" 49 | expectpart "$(echo -n "the Theodorcib bold" | $cligen_file -f $fspec)" 0 "" 50 | 51 | newtest "^Y line scroll" 52 | expectpart "$(echo -n "ruled over the shores of the Hreiðsea " | $cligen_file -s 1 -f $fspec)" 0 "the shores of the Hreisea" 53 | 54 | newtest "^Y page scroll" 55 | expectpart "$(echo -n "ruled over the shores of the Hreiðsea " | $cligen_file -s 0 -f $fspec)" 0 "the shores of the Hreisea" 56 | 57 | newtest "search ^R" 58 | expectpart "$(echo -n "Theodoric ruled Theo " | $cligen_file -f $fspec)" 0 "Theodoric the bold" 59 | 60 | newtest "search ^R^S" 61 | expectpart "$(echo -n "Theojfforic123 Theodoric Theosdajv Theo " | $cligen_file -f $fspec)" 0 "Theodoric the bold" 62 | 63 | newtest "^W" 64 | expectpart "$(echo -n "TheodoricThe " | $cligen_file -f $fspec)" 0 "Theodoric the bold" 65 | 66 | # XXX No functional tests 67 | newtest "ANSI arrows right/left/del" 68 | expectpart "$(echo -n "Theodoric [3 " | $cligen_file -f $fspec 2>&1)" 0 "Theodoric" "chief" 69 | 70 | # XXX: does not work "ruled over the shores of the Hreiðsea" 71 | newtest "UTF-8: UTF-2" 72 | expectpart "$(echo -n "ruled over the shores of the Hreiðsea " | $cligen_file -f $fspec -u 2>&1)" 0 "ruled over the shores of the Hrei" "ð" 73 | 74 | newtest "UTF-8: UTF-3/4" 75 | expectpart "$(echo -n "𤭢 € ¢ " | $cligen_file -f $fspec -u 2>&1)" 0 "𤭢" "€" "¢" "Unknown command" 76 | 77 | newtest "exit" 78 | expectpart "$(echo -n "Theodoric the bold " | $cligen_file -f $fspec 2>&1)" 0 "Theodoric the bold" 79 | 80 | newtest "endtest" 81 | endtest 82 | 83 | rm -rf $dir 84 | -------------------------------------------------------------------------------- /test/test_reftree.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # CLI variable preference 3 | # tests multiple variable matches with different preferences 4 | # Also test reference using filter statements: @, @remove: