improve of cmpl.
[bush.git] / tools / scripttest / envar.shlib
blob758edf0cf6846f61322c682ebc7984cbb5955624
1 #!/bin/bash
2 ############################################################
3 # source: envar.shlib
4 # author: CottonCandyOwner(CottonCandyOwner@126.com)
5 # date: 2022-08-25
6 ############################################################
7 # Copyright (C) 2022- Free Software Foundation, Inc.
8 # This configure script is free software; the Free Software
9 # Foundation gives unlimited permission to copy, distribute
10 # and modify it.
11 ############################################################
12 # note:
13 # envar is a envrionment variable that consisted by
14 # several part of string with the seperator '::'.
15 # it is used by 'envar' in imi file, or catalog node
16 # envar variable.
17 # it uses ATTR__ prefix to make difference from other
18 # variables.
20 ############################################################
24 # todo:
25 # @ does it need to add a pfx 'ATTR__' for all envar?
26 # @ add declare/local/global/readonly/export/unset/env/printenv redefine.
27 # testing for them, get the time compare with default cmd. testing
28 # for normal invoking, and the wortest complex condition.
32 # @ name of variable defination
33 # all variable names add a prefix with 'ATTR__', it means the variable is an envar.
34 # all function names add a prefix with 'FUNC::', it means the function is a method.
35 # when the list operation is doing, it can recognize envar and method easilly.
36 # 'FUNC__' is a reference variable prefix. it stored a function name to be invoked.
37 # the normal environment variable print cmd is invoked, it display variables without
38 # 'ATTR__' prefix. this kind of method is used to avoid large number of variables
39 # displayed on terminal.
42 . shlibinc
44 include stdio.shlib
45 include gplib.shlib
48 ##############################
49 # section: public comment info
50 ##############################
53 ##############################
54 # section: variable define
55 ##############################
57 envar_curr_domain=
58 envar_domain_list=
59 # it is defined in shlibinc. use file name as the module domain name.
60 envar_module_domain=envar
62 CFG_FUNC_NAME_COLON="true"
64 declare -g this=""
66 ##############################
67 # section: private function
68 ##############################
72 ##############################
73 # section: public function
74 ##############################
78 # not all the shell interpreter support function name with char of ':'.
79 # so it is defined as a variable. if the shell program does not support ':',
80 # modify code, and use '__' instead.
81 # defined with '::' can be displayed clearly, and less program processing.
83 # V_PFX="ATTR__"
84 # F_PFX="FUNC::"
85 # R_PFX="RFUNC__"
86 # if the shell script interpreter does not support ':', use "_" instead.
87 # F_PFX="FUNC__"
92 # fsyntax: envar_get_vname var
93 # fdesc: get vironment variable name string from param which is formatted
94 # as 'AAA::BBB::CCC', translate to 'AAA__BBB__CCC', whatever it is existing.
95 # if null string is used for varname, the script interpreter will
96 # report error, and it is not processed in code to cost down cpu
97 # usage.
99 envar_get_vname ()
101 local domain=
102 local name=$1
103 local vname=
105 # TBD: if there is a '@' pfx, use as an envar, or treat as a env var first.
106 if [[ "${1:0:1}" == '@' ]]; then
107 name="${1:1}"
108 else
109 name="${1}"
112 # try to match in domain list.
113 if [[ ${name:0:2} != '::' ]]; then
114 # domain list.
115 for domain in $envar_module_domain "" $envar_curr_domain $envar_domain_list; do
116 if [[ -n $domain ]]; then
117 vname="${domain}::$name"
118 vname="ATTR__${vname//::/__}"
119 else
120 vname="ATTR__${name//::/__}"
122 # dbgoutd "n.${vname}=${!vname}\n"
123 [[ -v "${vname}" ]] && echo "$vname" && return
124 done
126 # directly invoking to compactive to general using.
127 [[ -v "${name}" ]] && echo "$name" && return
128 else
129 # translate envar var name
130 # dbgoutd "name=$name\n"
131 vname=${name:2}
132 vname="ATTR__${vname//::/__}"
133 # dbgoutd "vname=$vname\n"
135 # dbgoutd "1.${vname}=${!vname}\n"
136 [[ -v "$vname" ]] && echo "$vname" && return
139 # if var is not exist, output original name string.
140 # echo $name
144 # fsyntax: envar_get_fname <var>
145 # fdesc: get function name string wether if it is exist or not.
147 envar_get_fname ()
149 local domain=
150 local name
151 local fname=$1
152 local vname=
154 # function patch.
155 # @ directly function defined by envar_func(), or method function maybe with '::' operator.
156 # @ use envar-var store function name
158 if [[ "${1:0:1}" == '@' ]]; then
159 name="${1:1}"
160 else
161 name="${1}"
164 # try to match in domain list.
165 if [[ ${fname:0:2} != '::' ]]; then
166 if [[ "$CFG_FUNC_NAME_COLON" == "true" ]]; then
167 for domain in $envar_module_domain "" $envar_curr_domain $envar_domain_list; do
168 [[ -n $domain ]] && domain="${domain}::"
169 fname="FUNC::${domain}${name}"
170 # dbgoutd "n.${fname}=${!fname}\n"
171 [[ $(is_func_defined $fname) == true ]] && echo "$fname" && return
172 vname="R${fname//::/__}"
173 [[ $(is_var_defined $vname) == true ]] && echo "${!vname}" && return
174 done
176 # use name directly without any prefix.
177 # put it in last, because it is few condition
178 # for normal function invoking by 'invoke'.
179 # dbgoutd "0.${name}=${!name}\n"
180 [[ $(is_func_defined $name) == true ]] && echo "$name" && return
181 [[ $(is_var_defined $name) == true ]] && echo "${!name}" && return
182 else
183 # domain list set by using.
184 for domain in $envar_module_domain "" $envar_curr_domain $envar_domain_list; do
185 [[ -n $domain ]] && domain="${domain}::"
186 fname="FUNC__${domain}${name//::/__}"
187 [[ $(is_func_defined $fname) == true ]] && echo "$fname" && return
188 vname="R${fname}"
189 [[ $(is_var_defined $vname) == true ]] && echo "${!vname}" && return
190 done
192 # use name directly without any prefix.
193 [[ $(is_func_defined $name) == true ]] && echo "$name" && return
194 vname="${name//::/__}"
195 [[ $(is_var_defined $vname) == true ]] && echo "${!vname}" && return
197 else
198 if [[ "$CFG_FUNC_NAME_COLON" == "true" ]]; then
199 fname="FUNC::${name:2}"
200 [[ $(is_func_defined $fname) == true ]] && echo "$fname" && return
201 vname="R${fname//::/__}"
202 [[ $(is_var_defined $vname) == true ]] && echo "${!vname}" && return
203 else
204 fname="FUNC__${name:2//::/__}"
205 [[ $(is_func_defined $fname) == true ]] && echo "$fname" && return
206 fname="R${fname}"
207 [[ $(is_var_defined $vname) == true ]] && echo "${!vname}" && return
211 # if var is not exist, output original name string.
212 # echo $name
216 # fsync: envar_mode <mode> <en/dis>
217 # fdesc: enable or disable for some features, such as readonly, associated array.
218 envar_mode ()
220 # TBD:
224 declare -g -a envar_tmp_initval=
227 # fsyntax: envar_create <envar-name> [= <value>]
228 # fdesc: alloc a envrionment variable, and assign value if
229 # it is needed. var name is consisted by 3 part described
230 # in envar-name paramter.
231 # set envar-var value whether it is exist or not.
232 # it always create envar-var in global domain.
234 envar_create ()
236 local operation=
237 local name=
238 local initval=
239 local expr=
240 local opt=
241 local pfx=
242 local sfx=
243 local tmp=
245 # dbgoutd create "$@\n"
246 # eval dbgoutd "\"envar_create \\\"$@\\\"\n\""
247 while [[ ${1: 0:1} == "-" ]]; do
248 opt+="$1"
249 shift
250 done
251 name=${1}
253 # keep array define in $@. $n maybe is a string with blanks.
254 if [[ "$1" =~ "=" ]]; then
255 # name and operator
256 if [[ "$1" =~ "+=" ]]; then
257 name="${1%%+=*}"
258 operation="+="
259 initval="${1#*+=}"
260 else
261 name="${1%%=*}"
262 operation="="
263 initval="${1#*=}"
265 # dbgoutd "initval=$initval\n"
267 shift
268 if [[ -z "$initval" ]]; then
269 initval="$1"
270 shift
273 # init value
274 expr="${initval[@]} $@"
275 # dbgoutd "initval=${expr}\n"
276 # dbgoutd "left_char=${initval:0:1}\n"
277 # dbgoutd "right_char=${expr: -1:1}\n"
279 tmp="${initval:0:1}${expr: -1:1}"
280 case $tmp in
281 '()' )
282 initval="${initval:1}"
283 [[ -z "$initval" ]] && initval="$1" && shift
285 # normal array
286 # dbgoutd "initval=${initval[@]}\n"
287 # dbgoutd "\$@=$@\n"
288 initval=( "$initval" "$@" )
289 tmp=${#@}
290 initval[$tmp]="${initval[$tmp]:0:-1}"
291 [[ -z "${initval[$tmp]}" ]] && unset initval[$tmp]
292 pfx="( "
293 sfx=" )"
295 '(*' | '*)' )
296 warn "one of '(' or ')' is not found!\n"
297 return
299 '*' )
300 # normal string value.
301 initval="$initval $@"
303 esac
304 elif [[ "${2:0:1}" == "=" || "${2:0:2}" == "+=" ]]; then
305 name="$1"
306 operation="${2%=*}="
307 initval=${2##*=}
308 shift 2
309 if [[ -z "$initval" ]]; then
310 initval="$@"
311 else
312 initval="$initval $@"
314 else
315 name="$1"
316 operation="="
317 initval=""
320 # ':::' pfx for global variable define without domain pfx appending.
321 # '::' pfx for global domain without module pfx.
322 if [[ ${name:0:3} == ':::' ]]; then
323 name="${name:3}"
324 elif [[ ${name:0:2} == '::' ]]; then
325 name="ATTR__${name:2}"
326 name="${name//::/__}"
327 else
328 tmp="$(envar_get_vname $name)"
330 if [[ -n $tmp ]]; then
331 # XXX: sometimes, re-create is a normal function feature.
332 #warn "envar '$name' has been created.\n"
333 # dbgoutd "existing $tmp=${!tmp}\n"
334 name=${tmp}
335 else
336 name="ATTR__${name//::/__}"
340 expr="declare -g $opt ${name}${operation}${pfx}\"\${initval[@]}\"${sfx}"
342 eval "${expr}"
343 # declare -p $name
346 fooo ()
348 unset envar_tmp_initval
349 declare -g -a envar_tmp_initval=
350 if [[ "${initval:0:1}" == '(' && "${initval: -1:1}" == ')' ]]; then
351 # the paramter of '-a' must after others, or others will be reported as an error.
352 # IFS_OLD=$IFS
353 # IFS=' '
354 read -a envar_tmp_initval < <(echo "${initval:1:-1}")
355 # IFS=$IFS_OLD
356 pfx="( "
357 sfx=" )"
358 initval="\"\${envar_tmp_initval[@]}\""
359 else
360 envar_tmp_initval="${initval#\ }"
361 initval="\"\${envar_tmp_initval[@]}\""
362 # pfx="\""
363 # sfx="\""
368 # fsyntax: envar_local <envar-name> [= <value>]
369 # fdesc: it's different from others. it create in current function. delate this
370 # envar-var when function return. and the access property is global. it
371 # can be accessed in any function it invoked. so it can be used as a paramter
372 # for function.
374 envar_local ()
376 local operation="="
377 local name=
378 local initval=
379 local expr="$@"
380 local opt=
381 local pfx=
382 local sfx=
384 while [[ ${expr:0:1} == "-" ]]; do
385 if [[ ${expr:0:2} == "-A" ]]; then
386 expr=${expr#-A\ }
387 opt+="-A "
388 elif [[ ${expr:0:2} == "-r" ]]; then
389 expr=${expr#-r\ }
390 opt+="-r "
391 else
392 expr=${expr#-[^\ ]\ }
394 done
395 name=${expr}
397 if [[ "$expr" =~ "=" ]]; then
398 name="${expr%%=*}"
400 name="${name%%\ *}"
401 initval="${expr#*=}"
402 initval="${initval#\ }"
404 if [[ ${name:-1:1} == "+" ]]; then
405 operation="+="
406 name=${name%+}
407 else
408 operation="="
410 else
411 name=$@
414 # ignor '::' pfx.
415 [[ ${name:0:2} == '::' ]] && name=${name:2}
417 expr="$(envar_get_vname $name)"
418 if [[ -n $expr ]]; then
419 name="$expr"
420 warn "envar '$name' has been created.\n"
421 else
422 name="ATTR__${name//::/__}"
425 unset envar_tmp_initval
426 declare -g -a envar_tmp_initval=
427 if [[ "${initval:0:1}" == '(' && "${initval: -1:1}" == ')' ]]; then
428 # the paramter of '-a' must after others, or others will be reported as an error.
429 read -a envar_tmp_initval < <(echo "${initval:1:-1}")
430 pfx="( "
431 sfx=" )"
432 initval="\"\${envar_tmp_initval[@]}\""
433 else
434 envar_tmp_initval="${initval#\ }"
435 initval="\"\${envar_tmp_initval[@]}\""
438 expr="declare -l $opt ${name}${operation}${pfx}${initval}${sfx}"
440 [[ -n $name ]] && eval "${expr}"
444 # fsync: envar_delete var
445 # fdesc: create the envar-var by paramter string.
446 envar_delete ()
448 local name=$(envar_get_vname $1)
449 local envarlist=
451 [[ "$1" == "::" ]] && eval unset \${!ATTR_*} && return
453 [[ -n ${!name} ]] && unset $name && return
455 eval envarlist=\${!${name}*}
456 for name in $envarlist; do
457 unset "$name"
458 done
462 # fsyntax: envar_create <envar-name> [= <value>]
463 # fdesc: it's different from create, it create envar-var in current module domain.
464 # invoke envar_create() in function, and invoke envar_decleare() in global define
465 # in src file.
467 envar_declare ()
469 local name="$@"
470 local opt=
472 if [[ ${name:0:2} =~ "-A" ]]; then
473 name=${name#-A\ }
474 opt="-A"
475 shift
478 if [[ ${name:0:2} != '::' && -n ${envar_module_domain} ]]; then
479 # current module domain define.
480 envar_create $opt ${envar_module_domain}::"$@"
481 else
482 # global define
483 envar_create $opt "$@"
488 # fsync: envar_array var[cnt1][cnt2]
489 # fdesc: create the envar-var by paramter string.
490 # 不更改作用域
491 envar_array ()
493 envar_create -A "$@"
497 # fsync: envar_readonly var[cnt1][cnt2]
498 # fdesc: create readonly envar.
499 envar_readonly ()
501 envar_create -r "$@"
505 # fsyntax: envar_dup <envar-name> <new-envar-name>
506 # fdesc: copy the content of envar variables.
508 envar_dup ()
510 local name=$(envar_get_vname $1)
511 local new=$2
512 local envarlist=
514 [[ -z $name ]] && return
516 envarlist=$(!name*)
517 for name in $envarlist; do
518 eval new=${name//${name}_/${2}_}
519 envar_create $new = "$(envar_get $name)"
520 done
524 # fsync: envar_rename var new-var
525 # fdesc: create the envar-var by paramter string.
526 envar_rename ()
528 local name=$(envar_get_vname $1)
529 local new=$2
530 local envarlist=
532 [[ -z $name ]] && return
534 envarlist=$(!name*)
535 for name in $envarlist; do
536 eval new=${name//${name}_/${2}_}
537 envar_create $new = "$(envar_get $name)"
538 envar_delete $name
539 done
543 # fsync: envar_export var
544 # fdesc: export variable.
545 envar_export ()
547 local name=$(envar_get_vname $1)
548 local envarlist=
550 [[ -n ${!name} ]] && unset $name && return
552 eval envarlist=\${!${name}*}
553 for name in $envarlist; do
554 export "$name"
555 done
559 # fsync: envar_unexport var
560 # fdesc: export variable.
561 envar_unexport ()
563 local name=$(envar_get_vname $1)
564 local envarlist=
566 [[ -n ${!name} ]] && unset $name && return
568 eval envarlist=\${!${name}*}
569 for name in $envarlist; do
570 declare +x "$name"
571 done
575 # fsyntax: envar_array_get <envar-name>
576 # fdesc: get the value of envar var.
578 envar_array_get ()
580 local name="$(envar_get_vname $1)[@]"
582 # dbgoutd "envar_array_get() $1 ==> $name\n"
583 [[ -z $name ]] && return
585 [[ -n ${!name} ]] && echo -e "${!name}"
589 # fsyntax: envar_array_cnt <envar-name>
590 # fdesc: get the count of envar array.
592 envar_array_cnt ()
594 local name="$(envar_get_vname $1)[@]"
596 # dbgoutd "envar_array_get() $1 ==> $name\n"
597 [[ -z $name ]] && return
599 eval echo -e "\${#${name}}"
603 # fsyntax: envar_get <envar-name>
604 # fdesc: get the value of envar var.
606 envar_get ()
608 local name=$(envar_get_vname $1)
609 local tmp=
610 local abc=
612 # dbgoutd "name=$name\n"
613 # dbgoutd "envar_get() $1 ==> $name\n"
614 [[ -z $name ]] && return
616 # xxx_on_get() proc.
617 [[ $(is_func_defined ${name}_on_get) == true ]] && ${name}_on_get ${name} "${operation}" "${pfx}${initval}${sfx}"
619 # XXX: here the '\n' maybe not append.
620 [[ -n ${!name} ]] && echo -ne "${!name}\n"
624 # fsyntax: envar_set <envar-name> [= <value>]
625 # fdesc: set envar-var value if it is exist.
627 envar_set ()
629 local operation="="
630 local name=
631 local initval=
632 local expr="$@"
633 local opt=
634 local pfx=
635 local sfx=
637 if [[ "$expr" =~ "=" ]]; then
638 name="${expr%%=*}"
640 name="${name%%\ *}"
641 initval="${expr#*=}"
642 initval="${initval#\ }"
644 if [[ ${name:-1:1} == "+" ]]; then
645 operation="+="
646 name=${name%+}
647 else
648 operation="="
650 else
651 name=$@
654 # ignor '::' pfx.
655 [[ ${name:0:2} == '::' ]] && name=${name:2}
657 expr="$(envar_get_vname $name)"
658 if [[ -z $expr ]]; then
659 warn "envar '$name' has not been created.\n"
660 return
661 # else
662 # name="ATTR__${name//::/__}"
664 name="$expr"
666 unset envar_tmp_initval
667 declare -g -a envar_tmp_initval=
668 if [[ "${initval:0:1}" == '(' && "${initval: -1:1}" == ')' ]]; then
669 # TBD: here should be improved.
670 # the paramter of '-a' must after others, or others will be reported as an error.
671 read -a envar_tmp_initval < <(echo "${initval:1:-1}")
672 pfx="( "
673 sfx=" )"
674 initval="\"\${envar_tmp_initval[@]}\""
675 else
676 envar_tmp_initval="${initval#\ }"
677 initval="\"\${envar_tmp_initval[@]}\""
680 expr="declare -g ${name}${operation}${pfx}${initval}${sfx}"
682 # dbgoutd "envar_tmp_initval=${envar_tmp_initval[@]}\n"
683 # dbgoutd "expr=$expr\n"
684 # xxx_on_set() proc.
685 [[ $(is_func_defined ${name}_on_set) == true ]] && ${name}_on_set ${name} "${operation}" "${pfx}${initval}${sfx}"
686 # set -x
687 [[ -n $name ]] && eval "${expr}"
688 # eval dbgoutd "${name}=\${${name}[@]}\n"
689 # set +x
693 # fsync: envar_is_valid var
694 # fdesc: check the envar if it is exist.
695 # or use [[ -v ATTR_XXX__domain__subitem ]] in code.
696 envar_is_valid ()
698 if [[ -n "$(envar_get_vname $1)" ]]; then
699 echo true
700 else
701 echo false
706 # fsync: envar_type <envar-name>
707 # fdesc: it check the type of envar, output 'env', 'var', 'func', 'vfunc'.
708 envar_type ()
710 local vname=
712 [[ ${1: 0:3} == ':::' && -v ${1:3} ]] && echo env && return
714 vname="$(envar_get_vname $1)"
716 # dbgoutd "vname=$vname\n"
717 if [[ -n "${vname}" ]]; then
718 if [[ -n "$(envar_get_fname ${!vname})" ]]; then
719 echo vfunc
720 else
721 echo envar
723 elif [[ -n "$(envar_get_fname ${1})" ]]; then
724 echo func
725 else
726 echo unkown
731 # fsync: envar_listvar
732 # fdesc: list all env-var for envar in current process.
733 envar_listvar ()
735 echo "${!ATTR__*}" | tr -s ' ' $'\n'
739 # fsync: envar_list
740 # fdesc: list all envar-var in current process.
741 envar_list ()
743 local data=
745 while read data; do
746 data=${data:6}
747 echo "${data//__/::}"
748 done < <(echo "${!ATTR__*}" | tr -s ' ' $'\n')
752 # fsync: envar_listofvar var
753 # fdesc: list envar under a var.
754 envar_listofvar ()
756 local data=
757 local vname=
758 local vprefix="${1//::/__}"
760 if [[ $1 != "::" ]]; then
761 [[ ${vprefix:0:2} != '__' ]] && vprefix="__${envar_module_domain}__${vprefix}__"
764 while read data; do
765 [[ -z $data ]] && continue
766 # eval vname=\${data//ATTR$vprefix}
767 # echo "${vname}"
768 echo "${data}"
769 done < <(eval "echo \"\${!ATTR$vprefix*}\"" | tr -s ' ' $'\n')
773 # fsync: envar_listof var
774 # fdesc: list envar under a var.
775 envar_listof ()
777 local data=
778 local vname=
779 local vprefix="${1//::/__}"
781 if [[ $1 != "::" ]]; then
782 if [[ ${vprefix:0:2} != '__' ]]; then
783 vprefix="__${envar_module_domain}__${vprefix}__"
784 else
785 vprefix="${vprefix}__"
789 while read data; do
790 [[ -z $data ]] && continue
791 eval vname=\${data//ATTR$vprefix}
792 vname="${vname//__/::}"
793 vname="${vname##::}"
794 echo "${vname}"
795 done < <(eval "echo \"\${!ATTR$vprefix*}\"" | tr -s ' ' $'\n')
799 # fsync: envar_listunder var
800 # fdesc: list envar just under a var directly.
801 envar_listunder ()
803 local data=
804 local list=
806 while read data; do
807 list="${data#$1}"
808 [[ ! "${list}" =~ :: ]] && echo "${list}"
809 done < <(envar_listof $1) | sort -u
813 # fsync: envar_foreach venvar proc
814 # fdesc: ergodic the member var under envar-var.
815 envar_foreach ()
817 local data=
818 local vname=
819 local vprefix="${1//::/__}"
821 # [[ -z $2 ]] && warn "proc function does not spedified in paramter.\n" && return
822 # [[ $(is_func_defined $2) == false ]] && warn "proc function '$2' does not defined.\n" && return
824 if [[ $1 != "::" ]]; then
825 [[ ${vprefix:0:2} != '__' ]] && vprefix="__${envar_module_domain}__${vprefix}__"
828 while read data; do
829 [[ -z $data ]] && continue
830 eval vname=\${data//ATTR$vprefix}
831 vname="${vname//__/::}"
832 # echo "${vname}"
833 $2 "${vname}" "${data}"
834 done < <(eval "echo \"\${!ATTR$vprefix*}\"" | tr -s ' ' $'\n')
838 # fsync: envar_expr venvar=xxx
839 # envar_expr ::var=venvar
840 # fdesc: dispatch the calculation expr of envar-var.
841 envar_expr ()
843 # TBD:
847 ##################################
848 # type & entity
849 ##################################
852 # XXX:
853 # 'type' maybe called with 'sectype', it means a type define for section in imi file.
854 # it will mix with other program language by using 'type'.
858 # create a type.
859 envar_type_create ()
865 # define envar under a type.
866 envar_type_def ()
872 # define a entity by the specified type.
873 envar_type_entity ()
879 # define envar under a type.
880 envar_type_def ()
886 ###########################################################################
887 # func/vfunc/alias
888 ###########################################################################
892 # fsync: envar_alias func_var func-name
893 # fdesc: create the envar-var by paramter string.
894 # var::sub::method ()
895 envar_alias ()
897 # TBD:
902 # fsync: envar_vfunc var::sub::method()
903 # fdesc: virtual function defination. it is stored in a reference envar variable.
904 envar_vfunc ()
910 # fsync: envar_func var::sub::method()
911 # fdesc: create the envar-var by paramter string.
912 # # 数组中的max-cnt,或结构体的成员变量数
913 # 或命名为method(),表示一个method的定义。
914 envar_func ()
916 local fname=
917 local param="$@"
918 local tmp=
919 local i
920 local j
922 # it can use char ":" in function name
923 fname="${1}"
924 param=${param#*[}
925 param=${param%]*}
927 OLD_IFS=$IFS
928 IFS=","
929 param=( $param )
930 param_type_list=( )
931 param_name_list=( )
933 # add domain prefix
934 if [[ ${vname:0:2} != '::' ]]; then
935 fname="$envar_module_domain::$fname"
938 IFS=" "
939 for (( i=${#param[@]}-1; i>=0; i-- )); do
940 tmp=( ${param[$i]} )
941 for (( j=${#tmp[@]}-1; j>=0; j-- )); do
942 [[ -z ${tmp[$j]} ]] && continue
944 # ignor var qualifier
945 if [[ -z ${param_name_list[$i]} ]]; then
946 param_name_list[$i]=${tmp[$j]}
947 elif [[ -z ${param_type_list[$idx]} ]]; then
949 else
950 break
952 done
953 done
954 IFS=$OLD_IFS
956 alias {="
957 unalias { ;
958 function $fname () {
959 `for (( i=${#param_name_list[@]}-1;i >= 0; i-- )); do
960 echo -ne \"local \${param_name_list[\$i]}=\\\${$(( i + 1 ))}\";
961 echo -ne \"\n\";
962 done; ` "
966 # fsync: envar_invoke param_list
967 # envar_invoke [[param_list, ...]]
968 # fdesc: create the envar-var by paramter string.
969 envar_invoke ()
971 local name=$1
972 local domain=
973 local cmd="$*"
975 cmd=${cmd#*[}
976 cmd=${cmd%]*}
977 IFS_OLD=$IFS
978 IFS=','
979 cmd=( ${cmd} )
981 name=$(envar_get_fname $1)
982 [[ -z $name ]] && $name "${cmd[@]}" && return $?
985 # 设置作用域。::表示global起始的作用域,未添加时,使用using作用域中的pfx。..表示回退一级作用域,以::代替/,用于多级作用域表示。
988 # fsync: envar_domain domain
989 # fdesc: switch 'CURRENT' domain as a dir operation.
990 envar_domain ()
992 if [[ ${1:0:2} == '::' ]]; then
993 envar_curr_domain="${1:2}"
994 elif [[ ${1:0:2} == '..' ]]; then
995 envar_curr_domain="${envar_curr_domain%::*}"
996 elif [[ -z ${1} ]]; then
997 envar_curr_domain=""
998 else
999 envar_curr_domain="$envar_curr_domain::$1"
1004 # fsync: envar_using domain
1005 # fdesc: append domain prefix.
1006 envar_using ()
1008 envar_domain_list+="$1 "
1012 # fsync: envar_unuse domain
1013 # fdesc: delete domain prefix.
1014 envar_unuse ()
1016 if [[ "$envar_curr_domain" =~ '$1' ]]; then
1017 envar_domain_list="${envar_curr_domain//$1/}"
1024 ###############################################################################################
1027 ##############################
1028 # section: file tail
1029 ##############################
1033 # fsync: envar_listofvar var
1034 # fdesc: list envar under a var.
1035 envar_listoftype ()
1037 local data=
1038 local vname=
1039 local vprefix="${1//::/__}"
1041 # if [[ $1 != "::" ]]; then
1042 [[ ${vprefix:0:2} != '__' ]] && vprefix="__${envar_module_domain}__${vprefix}"
1043 # fi
1045 [[ -v "ATTR__T${vprefix}" ]] && echo "${1}"
1047 # echo "vprefix=ATTR__T$vprefix"
1048 # eval echo "list=\${!ATTR__T$vprefix*}"
1049 # static member
1050 while read data; do
1051 [[ -z $data ]] && continue
1052 # echo v=$data
1053 [[ $data =~ ^ATTR__T[DVFR]?${vprefix}(.*)$ ]] && vname=${BASH_REMATCH[1]}
1054 # eval vname=\${data#ATTR__T}
1055 # eval vname=\${data#^__${vprefix}/}
1056 [[ ${vname:0:2} == '__' ]] && vname=${vname:2}
1057 # this statement does not works.
1058 # vname="${vname//[[:alnum:]]*__/ }"
1059 [[ -n "${vname}" ]] && sed -e "s/[[:alnum:]]*__/XXX::/g" <<< "${vname}"
1060 # [[ -n "${vname}" ]] && echo " ${vname//__/::}"
1061 done < <(eval "echo \"\${!ATTR__T$vprefix*} \${!ATTR__TD$vprefix*} \${!ATTR__TV$vprefix*} \${!ATTR__TF$vprefix*} \${!ATTR__TR$vprefix*} \"" | tr -s ' ' $'\n')
1063 # run time member
1064 while read data; do
1065 [[ -z $data ]] && continue
1066 [[ $data =~ ^type ]] && continue
1068 #eval vname=\${data//ATTR__T$vprefix}
1069 echo " ${data}"
1070 done < <(eval "echo \"\${!ATTR__T$vprefix}\"" | tr -s ' ' $'\n')
1072 #echo ${vname//[[:alnum:]]*__/$'\t'}
1073 #echo ${vname//[[:alnum:]]*__/ }
1076 # fsync: envar_listofvar var file
1077 # fdesc: list envar under a var.
1078 envar_listofvar_dump2file ()
1080 local data=
1081 local vname=
1082 local vprefix="${1//::/__}"
1084 if [[ $1 != "::" ]]; then
1085 [[ ${vprefix:0:2} != '__' ]] && vprefix="__${envar_module_domain}__${vprefix}__"
1088 eval "echo \"\${!ATTR$vprefix*}\"" | tr -s ' ' $'\n' |
1089 while read data; do
1090 [[ -z $data ]] && continue
1091 eval vname=\${data//ATTR$vprefix}
1092 echo "${vname}"
1093 done > $2
1098 # fsync: envar_memberof var
1099 # fdesc: list the sub envar-var under a domain or an envar-var.
1100 # # 结构体变量中的member列表,包括函数
1101 envar_memberof ()