Copyright (C) 2016, 2017, 2018, 2019, 2020, 2021  Stefan Vargyas

This file is part of Json-Type.

Json-Type is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Json-Type is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Json-Type.  If not, see <http://www.gnu.org/licenses/>.

--------------------------------------------------------------------------------

The Shell Function Meta-Tool 'gen-func'
=======================================

This document gives an account about the way the shell function 'gen-func' is
used within Json-Type.

Simply put, the shell function 'gen-func' generates the text of trie lookup C++
function associated to given set of keywords. The output of the 'grep' command
below shows that for now four of Json-Type's source files were using 'gen-func':

  $ format() { ssed -R 's/^/\n# /;s/(:\d+:)/\1\n/;s|(?<=\n)//\s*||;s/(?<!ssed -R)\s+(?=\x27)/ \\\n/g;s/(?<=[{|])\s*/ \\\n/g'; }

  $ grep src lib -R --include='*.[hc]' -Pne '\|\s*gen-func\b' --color=none|format

  # src/long-opts-impl.h:37:
  $ gen-long-opts-func0() { \
  local d=''; [ "$1" == "--debug" ] && d="$1"; long-opts $d -n| \
  gen-func -r- -f lookup_long_opt -e-1 -Pf -uz| \
  ssed -R '1s/^/static /'; }

  # src/common.c:1057:
  $ print \
  'v validate =options_validate_typelib_func' \
  'p print =options_print_typelib_func' \
  'a attr =options_attr_typelib_func' \
  'c check check-attr =options_check_typelib_func' \
  'A print-check print-check-attr =options_print_check_typelib_func' \
  'd gen-def =options_def_typelib_func'| \
  gen-func -f lookup_typelib_func_name| \
  ssed -R '1s/^/static /;1s/\s*result_t\&/\n\tenum options_typelib_func_t*/;s/(?=t =)/*/;s/result_t:://'

  # src/common.c:1193:
  $ print \
  'error =options_sigpipe_act_error' \
  'no-error =options_sigpipe_act_no_error' \
  'ignore =options_sigpipe_act_ignore'| \
  gen-func -f lookup_sigpipe_act_name| \
  ssed -R '1s/^/static /;1s/\s*result_t\&/\n\tenum options_sigpipe_act_t*/;s/(?=t =)/*/;s/result_t:://'

  # lib/test-gen-expr.c:194:
  $ print links graph| \
  gen-func -f options_lookup_tree_repr -r options_tree_repr_t -Pf -q \!strcmp| \
  adjust-func

  # lib/test-gen.c:187:
  $ print \
  'o object' \
  'd dict'| \
  gen-func -f options_lookup_json_type -r options_json_type_t| \
  adjust-func

  # lib/json-type.c:204:
  $ print type name plain| \
  gen-func -f json_type_ruler_lookup_obj_first_key -r json_type_ruler_obj_first_key_t| \
  adjust-func

  # lib/json-type.c:250:
  $ print object array list dict| \
  gen-func -f json_type_ruler_lookup_obj_type -r json_type_ruler_obj_type_t| \
  adjust-func

  # lib/json-type.c:492:
  $ print null type boolean number string object array| \
  gen-func -f json_type_ruler_is_basic_type -r json_type_ruler_basic_type_t| \
  adjust-func

  # lib/json-litex.c:1790:
  $ json-expr-builtins| \
  gen-func -f json_litex_expr_lookup_def_builtin_name -Pf -e NULL -u| \
  ssed -R '1s/^/static /;1s/(?<=\()/\n\t/;1s/\bresult_t\&/const struct json_litex_expr_builtin_t**/;s/(?=t =)/*/;s/result_t:://'

  # lib/json-litex.c:6025:
  $ cut -d $'\t' -f1 time-zones.txt| \
  gen-func -f json_litex_expr_parse_time_zone -r- -m-| \
  adjust-func

  # lib/json-litex.c:12003:
  $ print \
  'flat =json_litex_opts_expr_compiler_flat' \
  'ast =json_litex_opts_expr_compiler_ast'| \
  gen-func -f json_litex_opts_lookup_expr_compiler_name -Pf -q \!strcmp| \
  ssed -R '1s/^/static /;1s/(?<=\()/\n\t/;1s/\bresult_t\&/enum json_litex_opts_expr_compiler_t*/;s/(?=t =)/*/;s/result_t:://'

  # lib/json-litex.c:12039:
  $ print \
  'error =json_litex_opts_unexpect_lit_error' \
  'ignore =json_litex_opts_unexpect_lit_ignore'| \
  gen-func -f json_litex_opts_lookup_unexpect_lit_name -Pf -q \!strcmp| \
  ssed -R '1s/^/static /;1s/(?<=\()/\n\t/;1s/\bresult_t\&/enum json_litex_opts_unexpect_lit_t*/;s/(?=t =)/*/;s/result_t:://'

  # lib/json-litex.c:12081:
  $ print \
  'expanded =json_litex_opts_trie_path_expanded' \
  'function =json_litex_opts_trie_path_function'| \
  gen-func -f json_litex_opts_lookup_trie_path_name -Pf -q \!strcmp| \
  ssed -R '1s/^/static /;1s/(?<=\()/\n\t/;1s/\bresult_t\&/enum json_litex_opts_trie_path_t*/;s/(?=t =)/*/;s/result_t:://'

  # lib/json-litex.c:12117:
  $ print \
  'builtin =json_litex_opts_path_eq_builtin' \
  'strcmp =json_litex_opts_path_eq_strcmp'| \
  gen-func -f json_litex_opts_lookup_path_eq_name -Pf -q \!strcmp| \
  ssed -R '1s/^/static /;1s/(?<=\()/\n\t/;1s/\bresult_t\&/enum json_litex_opts_path_eq_t*/;s/(?=t =)/*/;s/result_t:://'

  # lib/json-litex.c:12195:
  $ gen-long-opts-func0() { \
  local d=''; [ "$1" == "--debug" ] && d="$1"; long-opts $d -n| \
  gen-func -r- -f json_litex_opts_lookup_long_opt -e-1 -Pf -uz| \
  ssed -R '1s/^/static /;1s/(?<=\()/\n\t/'; }

  # lib/test-expr.c:367:
  $ print \
  'default =options_builtins_space_default' \
  'alpha =options_builtins_space_alpha'| \
  gen-func -f options_lookup_builtins_space_name -Pf -q \!strcmp| \
  ssed -R '1s/^/static /;1s/(?<=\()/\n\t/;1s/\bresult_t\&/enum options_builtins_space_t*/;s/(?=t =)/*/;s/result_t:://'

  # lib/test-expr.c:401:
  $ print \
  'flat =options_expr_compiler_flat' \
  'ast =options_expr_compiler_ast'| \
  gen-func -f options_lookup_expr_compiler_name -Pf -q \!strcmp| \
  ssed -R '1s/^/static /;1s/(?<=\()/\n\t/;1s/\bresult_t\&/enum options_expr_compiler_t*/;s/(?=t =)/*/;s/result_t:://'

  # lib/test-filter.c:203:
  $ print \
  'init =test_failure_type_init' \
  'handler =test_failure_type_handler' \
  'exec =test_failure_type_exec'| \
  gen-func -f test_options_lookup_fail_name -Pf -q \!strcmp| \
  ssed -R '1s/^/static /;1s/\s*result_t\&/ enum test_failure_type_t*/;1s/(?<=\()/\n\t/;s/(?=t =)/*/;s/result_t:://'

For example, the second entry in the list above shows that 'gen-func' produced
the complete code of function 'lookup_typelib_func_name' in 'src/common.c',
whereas the shell function is used three more times for providing trie lookup
functions in source file 'lib/json-type.c'.

Comments embedding meta-commands suggest that 'gen-func' is obtained by sourcing
in at the command line prompt the file 'lookup-gen/commands.sh':

  $ grep src lib -R --include='*.[hc]' -ne lookup-gen
  src/long-opts-impl.h:26:// $ . ~/lookup-gen/commands.sh
  src/common.c:1055:// $ . ~/lookup-gen/commands.sh
  lib/test-gen-expr.c:190:// $ . ~/lookup-gen/commands.sh
  lib/test-gen.c:183:// $ . ~/lookup-gen/commands.sh
  lib/json-type.c:200:// $ . ~/lookup-gen/commands.sh
  lib/json-litex.c:1788:// $ . ~/lookup-gen/commands.sh
  lib/test-filter.c:201:// $ . ~/lookup-gen/commands.sh

As a matter of fact, this is not completely true in the following sense. The time
Json-Type was initially developed, 'gen-func' was part of a private project of
mine, named Lookup Gen. However, after Json-Type became software libre, I made
Lookup Gen publicly available too, but with its name changed to Trie-Gen [1].

Trie-Gen's latest source release tarball is obtainable from [2]. Note that all
released tarballs are signed with GnuPG, therefore upon downloading e.g. version
0.6 by means of the following two commands:

  $ wget https://download.savannah.gnu.org/releases/trie-gen/trie-gen-0.6.tar.bz2

  $ wget https://download.savannah.gnu.org/releases/trie-gen/trie-gen-0.6.tar.bz2.sig

one has to issue two instances of 'gpg' program to check the integrity of the
received tarball (GnuPG FAQ [3]):

  $ gpg --recv-keys 3D805B7A

  $ gpg --verify trie-gen-0.6.tar.bz2.sig 

Of the two commands above, the former imports into the local keyring Trie-Gen
author's key, while the latter verifies the package signature -- thus validating
its integrity.

Instructions are given in '$TRIE_GEN_HOME/README' for configuring, building and
testing Trie-Gen. '$TRIE_GEN_HOME' is the path to the directory that hosts the
the content of the unpacked tarball. The primary documentation of Trie-Gen is to
be found in '$TRIE_GEN_HOME/doc/trie-gen.txt'.

Now, back to Json-Type, when needing to use 'gen-func', one has to source in
the bash shell script 'commands.sh' not from the 'lookup-gen' directory but
from where it is found in Trie-Gen's home directory:

  $ . $TRIE_GEN_HOME/commands.sh

Note that if '$TRIE_GEN_HOME' is not '$HOME/trie-gen', each call to 'gen-func'
must specify Trie-Gen's home directory via the command line options `-h|--home'.
Instead of having to pass in these options each time calling the shell function,
one could simply define the following alias:

  $ alias gen-func="gen-func -h $TRIE_GEN_HOME"


References
----------

[1] Trie-Gen: Trie Lookup Code Generator
    http://nongnu.org/trie-gen/

[2] Trie-Gen's Release Tarballs
    https://download.savannah.gnu.org/releases/trie-gen/

[3] GnuPG FAQ: How can I use GnuPG to verify a file I've downloaded?
    https://www.gnupg.org/faq/gnupg-faq.html#how_do_i_verify_signed_packages


