20230322
[shlib.git] / bin / shlibinc
blobe8fae166e4032b7887d9184dbbeb83af938a7927
1 #!/bin/bash
2 ############################################################
3 # source: shlibinc
4 # author: devenkong(18151155@qq.com)
5 # date: 2021-10-03
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 # this file define a cmd called 'include' which is used
14 # to include a shlib file.
15 # it define a shlib version variable SHLIB_VERSION, and
16 # ROOTFS to store root path in paticulor enviroument.
17 # sometimes, user need file include feature like shlib,
18 # so it define a cmd called 'define_include' to provide this
19 # feature.
20 # when i use 'source' in function, it can not load global
21 # variables in sourced file, so, this cmd is defined as an
22 # alias.
23 # when shlib code need to be updated in memory, reloadshlib()
24 # is used to do this work.
25 # shlib is included unique, if the shlib loaded in system/bash
26 # init script, and the global variable should be re-init in
27 # every program. so, cmd 'uniqlib' and 'endlib' is defined,
28 # try to load part of lib unique, and others executed every
29 # time. this feature have not been implemented.
30 ############################################################
33 # todolist:
34 # @ debug info output setting by global variable.
35 # @ combine include alias with define_include string.
36 # @ testing for load in different process.
40 # features:
41 # @ global include path.
42 # @ uniq-include.
43 # @ compactly load in sub-script-proc.
44 # @ include files in PWD.
45 # @
46 # @ if lib in different lib path with same name, they might be mixed.
47 # @ include ./scripts/uniq.shlib
48 # include uniq.shlib
49 # this will record different lib flag in SHLIB_INC_LIST.
50 # maybe use full-path-name will resolve this problem.
53 # @ [shlibinc] binary shlib check and load.
54 # for shlibinc, add a func/alias to check and load binary shlib.
55 # at the beginning of shlib src file, add a binary lib checking cmd. if the
56 # shlib implemented by a binary lib, load it first, and do not load script code
57 # below.
59 # interface:
61 # SHLIB_VERSION, shlib version infomation.
62 # include <shlib-file>, used to include a shlib in the process of current program.
63 # it will be uniq included in a process. once include, does not need to
64 # be 'source' again. but it still need to be included in a new sub-script
65 # program.
66 # load/unload <shlib-file>, used to load a shlib in system, or current session,
67 # or current process. the difference with include is that, it recode the
68 # global var & func & alias cmd in exported env var, and set them with
69 # export attribute. when the shlib would be load in a new script program,
70 # it still keep load content.
71 # reload <shlib-file>, used to load a shlib again if shlib is updated.
72 # PROG_GVAR_INIT <libname>, global variable init in shlib, when the lib file
73 # has been loaded.
74 # GVAR_INIT <libname>, global variable first init in shlib.
75 # uniqlib <libname>, skip loading the code after this cmd, if the shlib has
76 # been loaded.
77 # get_shlib_path, print shlib one path string by one line.
78 # get_shlib_path_var <var-name>, get the shlib path in var array.
79 # set_shlib_path <PATH>, set whole shlib path string.
80 # add_shlib_path <PATH>, append path to shlib path.
81 # del_shlib_path <PATH>, delete path by specified string.
82 # define_include <> <> <> <>, define a include cmd for a kind of lib file.
86 # enable alias feature in script.
87 shopt -s expand_aliases
89 # init ROOTFS if it is not /
90 if [[ ! -d $ROOTFS ]]; then
91 TMP_DIR=`dirname $(which ls)`/..
92 TMP_DIR=`cd $TMP_DIR; pwd; cd - > /dev/null`
93 ROOTFS=${ROOTFS:-$TMP_DIR}
94 unset TMP_DIR
98 # save current process id every time when this file is sourced in a program.
100 PROG_ID=$$
103 # shlib module name stack.
105 if [[ ! -v SHLIB_IDX || -z $SHLIB_IDX ]]; then
106 declare -g SHLIB_IDX=0
107 declare -g SHLIB_MODULE=${BASH_SOURCE[1]##*\/}
108 SHLIB_MODULE=${SHLIB_MODULE^^}
113 ##############################
114 # section: public comment info
115 ##############################
118 #echo SHLIB_VERSION=$SHLIB_VERSION
120 ##############################
121 # section: variable define
122 ##############################
125 # todo: comment this code, exported function cannot be use in sub-process.
128 # unique executing judged by shlib version variable.
129 #if [[ -n $SHLIB_VERSION ]]; then
131 # invoke global var init if this script file is invoked in a shlib
133 # [[ -n $1 ]] && PROG_GVAR_INIT $1
135 # echo shlibinc has been loaded, skip to save cpu cost.
138 # shlibinc only could be used by source
139 # use return to exit from current script file.
141 # return
146 # todo:
147 # if defined as exported var, it can be used for feature of one time code loading.
148 # but this feature can not works.
150 #declare -g -x
151 SHLIB_VERSION="0.0.1"
154 # it stored shlib paths like enviroument variable 'PATH'.
156 SHLIB_PATH=${SHLIB_PATH:-`echo $ROOTFS/usr/shlib:$ROOTFS/usr/libexec/dvar/shlib`}
158 path_list=
160 # an array of SHLIB_PATH path.
161 if [[ -z $path_list ]]; then
162 OLD_IFS=$IFS
163 IFS=":"
164 path_list=( $SHLIB_PATH )
165 IFS=$OLD_IFS
169 # @ include时,判断SHLIB_LIST,已include,skip。首次include中,调用_init()函数,设置SHLIB_LIST。
170 # @ load时,
171 # # 判断SHLIB_INC_LIST,已load,且判断SHLIB_LIST中未load,只调用_init()进行初始化+ 判断SHLIB_INC_LIST,已load,且判断SHLIB_LIST中已load,skip
172 # # 其它,首次load时,调用_init()函数,设置SHLIB_INC_LIST和当前进程的SHLIB_LIST。SHLIB_LIST在创建新进程时不export。
176 # fsyntax: decl_shlib_var <var-name>
177 # fdesc: check exist before var declare, and add SHLIB__ prefix.
179 decl_shlib_var ()
181 [[ ! -v SHLIB__${1^^} ]] && declare -g SHLIB__${1^^}
186 # LIST variable have not been used
188 if [[ ! -v SHLIB_INC_LIST ]]; then
189 declare -g SHLIB_INC_LIST=${SHLIB_INC_LIST=""}
191 if [[ ! -v SHLIB_LIST ]]; then
192 declare -g -x SHLIB_LIST=${SHLIB_LIST=""}
194 #SHLIB_LIST=${SHLIB_LIST=""}
197 [[ ! -v nest_level ]] && declare -g nest_level=0
199 [[ ! -v nest_level_shlib ]] && declare -g -a nest_level_shlib[0]=""
201 # load switchs
202 [[ ! -v shlib_load_state ]] && declare -g -a shlib_load_state[0]=0
204 # do not append -x attr, it should be resetted in sub-process.
205 [[ ! -v loading_flag ]] && declare -g -a loading_flag[0]=0
207 # TBD: this var should be used as a load type for shlib,
208 # code in shlib use it to set different variable type, -x or not.
209 [[ ! -v inc_flag ]] && declare -g -a inc_flag=""
210 [[ ! -v last_inc_flag ]] && declare -g last_inc_flag=""
213 ##############################
214 # section: private function
215 ##############################
218 # private dbgout function in this lib.
220 tmp_dbgout ()
222 echo -ne "$@\n" >&2
226 # private dbgout function in this lib.
228 misc_dbgout ()
230 if [[ ${SHLIB_DBGOUT_OPT} =~ ':shlibinc:' || ${SHLIB_DBGOUT_OPT} =~ ':shlibinc-misc:' ]]; then
231 echo -ne "$@\n" >&2
236 # private dbgout function in this lib.
238 list_dbgout ()
240 if [[ ${SHLIB_DBGOUT_OPT} =~ ':shlibinc:' || ${SHLIB_DBGOUT_OPT} =~ ':shlibinc-list:' ]]; then
241 echo -ne "$@\n" >&2
246 # private dbgout function in this lib.
248 inc_dbgout ()
250 if [[ ${SHLIB_DBGOUT_OPT} =~ ':shlibinc:' || ${SHLIB_DBGOUT_OPT} =~ ':shlibinc-inc:' ]]; then
251 echo -ne "$@\n" >&2
256 # fsyntax: get_vname_pfx
257 # fdesc: get translate vname string by a function, so that the shlib
258 # prefix uses the same syntax by a function.
260 get_vname_pfx ()
262 local vname=
264 vname=${1//[^[:alnum:]_]/_}
265 vname=${vname^^}
266 echo "$vname"
267 # nEKfP=${nEKfP%%\.*}
268 # nEKfP=${nEKfP##*/}
270 # vname="$(basename ${1})"
271 # vname="$(echo $1 | cksum | cut -d ' ' -f1)_${vname//[^_[:alnum:]]/_}"
275 # fsyntax: alias_redefine
276 # fdesc: it re-define an alias cmd for a shlib load in new process.
278 alias_redefine ()
280 local vname=$(get_vname_pfx "$1")
282 list_dbgout "######################################################"
283 list_dbgout "alias_redefine()"
284 dbgout_print_elemlist "$1"
286 list2_name="aliaslist2_$vname"
287 list_dbgout "${!list2_name}"
288 eval ${!list2_name}
291 # get func list in current process.
292 get_func_list ()
294 local data=
296 while read data; do
297 data="${data##* }"
298 echo -ne "${data}\n"
299 done < <(declare -F)
302 # get var list in current process.
303 get_var_list ()
305 local data=
307 while read data; do
308 data="${data%%=*}"
309 data="${data##* }"
310 echo "${data}"
311 done < <(declare -p | grep -e "declare" | sed -e "s/^.*-f.*$//g")
312 # declare -F | grep -E "declare" | sed -e "s/^.*-f.*$//g"
315 # get alias list in current process.
316 get_alias_list ()
318 local data=
320 while read data; do
321 echo "${data}"
322 done < <(alias | grep -e "^alias")
326 # fsyntax: get_elem_list null <switchs> <lib-name>
327 # fdesc: get var/func/alias list in current process. it is used for comparing
328 # with the list after shlib load.
330 get_elem_list ()
332 local vname=$(get_vname_pfx "$3")
334 # when it was a pure include invoking, do not
335 # record elem-list.
336 [[ -z $2 || "$2" != "load" ]] && return
338 declare -g funclist1_$vname=""
339 eval funclist1_$vname=\"\$\(get_func_list\)\"
341 declare -g varlist1_$vname=""
342 eval varlist1_$vname=\"\$\(get_var_list\)\"
344 declare -g aliaslist1_$vname=""
345 eval aliaslist1_$vname=\"\$\(get_alias_list\)\"
349 # fsyntax: get_curr_elem_list <lib-name> <switchs>
350 # fdesc: get var/func/alias list in current process. it is used for comparing
351 # with the list after shlib load.
353 get_curr_elem_list ()
355 local libname=
356 local vname=
357 local data=
358 local list_name=
359 local list2_name=
360 local pfx=
362 [[ ! -v nest_level ]] && declare -g nest_level=""
364 printf -v pfx "%*s" $(( nest_level * 4 )) " "
365 list_dbgout "${pfx}get_curr_elem_list ($(basename $1), $2, nest_level=$nest_level)"
367 # save current elem_list for last level
368 if [[ $nest_level != 0 && -n "${nest_level_shlib[$nest_level]}" ]]; then
369 # list_dbgout nest_level=$nest_level
370 printf -v pfx "%*s" $(( nest_level * 4 )) " "
371 list_dbgout "${pfx}\033[33msave_lib_elem_list(null, ${shlib_load_state[$nest_level]}, ${nest_level_shlib[$nest_level]}, nest_level=$nest_level)\033[0m\n"
372 save_lib_elem_list null ${shlib_load_state[$nest_level]} "${nest_level_shlib[$nest_level]}"
375 # record nest level
376 # this code is running in a `` sub-proc.
377 # print ": $((nest_level++))" to update the value in parent process.
378 nest_level=$(( nest_level + 1 ))
379 nest_level_shlib[$nest_level]="$3"
380 shlib_load_state[$nest_level]="$2"
381 loading_flag[$nest_level]="$inc_flag"
383 # get current elem_list for current level
384 get_elem_list "$1" "$2" "$3"
385 printf -v pfx "%*s" $(( nest_level * 4 )) " "
386 list_dbgout "${pfx}\033[0mxxx get_elem_list($(basename $1), $2, nest_level=$nest_level)\033[0m"
390 # fsyntax: save_curr_lib_elem_list <lib-path> <switch> <lib-name>
391 # fdesc: get current var/func/alias list again, and comparing with the one saved
392 # in get_curr_elem_list(), output tree array list of var/func/alias, which
393 # is appended by the loaded shlib.
395 save_curr_lib_elem_list ()
397 local pfx=
399 printf -v pfx "%*s" $(( nest_level * 4 )) " "
400 list_dbgout "${pfx}\033[0mxxx save_curr_lib_elem_list($(basename $1), $2, nest_level=$nest_level)\033[0m"
402 # release last level elem.
403 unset loading_flag[$nest_level]
404 unset nest_level_shlib[$nest_level]
405 unset shlib_load_state[$nest_level]
407 nest_level=$(( nest_level - 1 ))
408 #nest_level_shlib[$nest_level]="$1"
410 save_lib_elem_list "$@"
412 if [[ -n "${nest_level_shlib[$nest_level]}" ]]; then
413 get_elem_list "null" "${shlib_load_state[$nest_level]}" "${nest_level_shlib[$nest_level]}"
414 printf -v pfx "%*s" $(( nest_level * 4 )) " "
415 list_dbgout "${pfx}\033[0mxxx get_elem_list($(basename ${nest_level_shlib[$nest_level]}), $2, nest_level=$nest_level)\033[0m"
419 dbgout_print_elemlist ()
422 local vname=$(get_vname_pfx "$1")
424 tmp_dbgout "\$1=$1\n"
425 tmp_dbgout "vname=$vname\n"
427 list2_name="varlist2_$vname[@]"
428 echo "${list2_name}=${!list2_name}"
429 declare -p varlist2_$vname
431 list2_name="funclist2_$vname[@]"
432 echo "${list2_name}=${!list2_name}"
433 declare -p funclist2_$vname
435 list2_name="aliaslist2_$vname[@]"
436 echo "${list2_name}=${!list2_name}"
437 declare -p aliaslist2_$vname
439 list_dbgout ""
443 # fsyntax: save_lib_elem_list null <switch> <lib-name>
444 # fdesc: get current var/func/alias list again, and comparing with the one saved
445 # in get_curr_elem_list(), output tree array list of var/func/alias, which
446 # is appended by the loaded shlib.
448 save_lib_elem_list ()
450 local vname=$(get_vname_pfx "$3")
451 local list_name=
452 local data=
453 local list2_name=
455 if [[ "$2" == "load" ]]; then
456 # for func list
457 list_name="funclist1_$vname"
458 list2_name="funclist2_$vname"
459 # unset $list2_name
460 declare -g -x $list2_name=""
461 # echo "$list2_name define:"
462 # declare -p $list2_name
463 # diff with the funclist saved before source operation.
464 while read data; do
465 # add -x option to function, so that sub-proc can use it without load again.
466 declare -f -x ${data##* }
467 # save to array.
468 eval $list2_name+="\"${data##* } \""
469 done < <(echo "${!list_name}" | diff --from-file=<(get_func_list) - | grep -e "<")
470 unset $list_name
471 list_dbgout "\033[34m==================================\033[0m\n"
472 list2_name="${list2_name}[@]"
473 list_dbgout "${!list2_name}\n"
474 # return
476 # for var list
477 list_name="varlist1_$vname"
478 list2_name="varlist2_$vname"
479 # unset $list2_name
480 declare -g -x $list2_name=""
481 get_var_list > ~/b.txt
482 while read data; do
483 # save to array.
484 # data="${data%=*}"
485 if [[ "$data" =~ 'funclist' || "$data" =~ 'varlist' || "$data" =~ 'aliaslist' ]]; then
486 # echo $data
487 continue
489 data="${data#*< }"
490 # list_dbgout "data=$data\n"
491 # echo $data
492 eval $list2_name+="\"\${data} \""
493 done < <(echo "${!list_name}" | diff --from-file=<(get_var_list) - | grep -e "<")
494 unset $list_name
495 list_dbgout "\033[44m==================================\033[0m\n"
496 eval list_dbgout \"\${$list2_name[@]}\" | tr ' ' $'
498 # return
500 # for alias list
501 list_name="aliaslist1_$vname"
502 list2_name="aliaslist2_$vname"
503 # unset $list2_name
504 declare -g -x $list2_name=""
505 while read data; do
506 # save to array.
507 data="${data%%=*}"
508 data="${data##*alias }"
509 eval $list2_name+="\"${data} \""
510 done < <(echo "${!list_name}" | diff --from-file=<(get_alias_list) - | grep -e "< alias")
511 ( eval list_dbgout \"\${$list2_name}\" ) | tr ' ' $'
513 eval $list2_name="\$(alias \${$list2_name})"
514 unset $list_name
515 list_dbgout "\033[44m==================================\033[0m\n"
516 ( eval list_dbgout \"\$list2_name=\${$list2_name}\" ) | tr ' ' $'\n'
517 list_dbgout "\033[44m==================================\033[0m\n"
521 elemlist_var_clear ()
523 local vname=$(get_vname_pfx "$1")
525 unset varlist2_$vname
526 unset funclist2_$vname
527 unset aliaslist2_$vname
531 # fsyntax: lib_load_prev <lib-path> <inc-type> <lib-name>
532 # fdesc: source lib file, and compare var/func/alias list between before and after of source.
533 # the name of lib must be an absolutly path for shlib file. switch enable the comparing
534 # feature.
535 # this function is used for nest inclussion, when some of the variable need to be local
536 # attribute variable.
538 lib_load_prev ()
540 # local libfile=$1
541 # local inc_type=$2
542 # local lib_name=$3
544 local vname=
545 local pfx=
546 local pwd=
547 local tmp=
549 if [[ $2 == load ]]; then
550 vname=SHLIB_LIST
551 else
552 vname=SHLIB_INC_LIST
555 # declare the variable, or it will be defined as a local variable.
556 declare -g $vname
557 # declare -p $vname
559 inc_dbgout "[$2]: XXXXXXXXXXX $1"
560 get_curr_elem_list $1 $2 $3
561 printf -v pfx "%*s" $(( nest_level * 4 )) " "
562 inc_dbgout "${pfx}[source]: $1\n"
564 # append variable like 'BASH_SOURCE'
566 tmp="${3##*\/}"
567 tmp="${tmp//\.shlib}"
568 # set -x
569 [[ ! -v SHLIB_IDX || -z $SHLIB_IDX ]] && SHLIB_IDX=0
570 declare -g SHLIB_MODULE_STK[$SHLIB_IDX]=$SHLIB_MODULE
571 declare -g SHLIB_MODULE=$(get_vname_pfx ${tmp^^})
572 declare -g SHLIB_IDX=$(( SHLIB_IDX + 1 ))
573 # set +x
575 pwd="$PWD"
576 cd $(dirname $1)
577 source $1
578 cd "$pwd"
580 # recovery
581 declare -g SHLIB_IDX=$(( ${SHLIB_IDX} - 1 ))
582 eval declare -g SHLIB_MODULE=${SHLIB_MODULE_STK[$SHLIB_IDX]}
583 unset SHLIB_MODULE_STK[$SHLIB_IDX]
585 if [[ $? == 0 ]]; then
586 eval "$vname+=\"
587 $1\""
588 # misc_dbgout "XXXXXXXXXXXXXXXX $3=${!3}=$1"
589 if [[ $2 == load ]]; then
590 # tmp="$(basename $1)"
591 # tmp="${tmp%\.*}"
593 # tmp=${tmp//[^[:alnum:]_]/_}
594 # GVAR_INIT ${tmp,,}
595 GVAR_INIT "$3"
597 else
598 echo -ne "err: source file($1) failed.\n" >&2
601 save_curr_lib_elem_list $1 $2 $3
605 # fsyntax: unlib_load_prev <lib-path> <inc-type> <lib-name>
606 # fdesc: source lib file, and compare var/func/alias list between before and after of source.
607 # the name of lib must be an absolutly path for shlib file. switch enable the comparing
608 # feature.
609 # this function is used for nest inclussion, when some of the variable need to be local
610 # attribute variable.
612 unlib_load_prev ()
614 local vname=$(get_vname_pfx "$3")
615 local listname=
616 local data=
617 local tmp=
619 # release var define.
620 listname="varlist2_$vname"
621 unset ${!listname}
623 # release function define.
624 listname="funclist2_$vname"
625 unset ${!listname}
627 # release function define.
628 listname="aliaslist2_$vname"
629 while read data; do
630 data=${data#*alias }
631 data=${data%%=*}
632 tmp+="$data "
633 done < <(echo "${!listname}" | grep -e "^alias ")
634 unalias ${tmp}
638 ##############################
639 # section: public function
640 ##############################
642 #alias shlibopt="source shlibopt.sh"
644 shlibopt ()
646 source shlibopt.sh $@
651 # 3 type of XXX_PROG_ID_FLAG
652 # @ XXX_PROG_ID_FLAG undefined, it means first time lib loading, invoke init function
653 # in GVAR_INIT, and do nothing in PROG_GVAR_INIT.
654 # @ XXX_PROG_ID_FLAG equal to $$, it means lib has been loaded in current process. do
655 # nothing either in PROG_GVAR_INIT or in GVAR_INIT. return from souce cmd.
656 # @ XXX_PROG_ID_FLAG not equal to $$, it means lib is loaded by session/system process,
657 # and it only need to re-init lib var in one time, but didn't load other functions.
658 # invoke init function in PROG_GVAR_INIT, and return from shlib 'source'(cmd not code),
659 # GVAR_INIT can not be invoked.
661 # there is a example:
662 # stdio.shlib has been loaded by 'include' in sysyem init. program named prog invoke
663 # include stdio.shlib, and shlib_templete.shlib. shlib_templete.shlib invoke include
664 # stdio.shlib. here stdio.shlib is loaded 3 times.
665 # @ first time in system init, and invoke var_init() in GVAR_INIT, while XXX_PROG_ID_FLAG
666 # is not defined.
667 # @ second time in 'prog', XXX_PROG_ID_FLAG is pid of session process, and not equal to
668 # current pid. so invoke var_init() in PROG_GVAR_INIT, and retrun from source cmd.
669 # @ the third time in shlib_templete.shlib, XXX_PROG_ID_FLAG is current pid, and do nothing,
670 # return from source cmd directly.
673 # todo:
674 # there are two condition in using. re-include when source include, or invoke in sub-process.
678 # fsyntax: PROG_GVAR_INIT
679 # fdesc: global variable init in shlib, when the lib file has been loaded.
680 # it checks variable setted by GVAR_INIT.
682 alias PROG_GVAR_INIT='
684 nEKfP=
685 input_nEKfP=
686 PFX_nEKfP=
687 flag_aFmIG=
688 func_aFmIG=
690 read -t 1 nEKfP
692 input_nEKfP="$nEKfP"
693 PFX_nEKfP=$(get_vname_pfx "$nEKfP")
694 nEKfP=${nEKfP%%\.*}
695 nEKfP=${nEKfP##*/}
697 flag_aFmIG="${PFX_nEKfP}_PROG_ID_FLAG"
698 func_aFmIG="$(declare -F shlib_${nEKfP,,}_init)"
700 if [[ -n ${!flag_aFmIG} && -n "$func_aFmIG" ]]; then
701 if [[ ${!flag_aFmIG} != $$ ]]; then
702 declare -g -x "${flag_aFmIG}=$$"
704 # re-define alias cmd automatically before init.
705 alias_redefine ${input_nEKfP}
708 # it will display error while readonly var is defined
709 # and setted again. odirect stderr to null,
710 # or process by shlib code.
712 nEKfP=${nEKfP,,}
713 shlib_${nEKfP}_init
714 inc_dbgout "${nEKfP} re-init.\n"
716 unset nEKfP
717 unset flag_aFmIG
718 unset func_aFmIG
722 unset nEKfP
723 unset flag_aFmIG
724 unset func_aFmIG
725 } <<<'
728 # fsyntax: GVAR_INIT
729 # fdesc: set mutex include flag.
731 alias GVAR_INIT='
733 nEKfP=
734 PFX_nEKfP=
735 flag_aFmIG=
737 read -t 1 nEKfP
739 PFX_nEKfP=$(get_vname_pfx "$nEKfP")
740 nEKfP=${nEKfP%%\.*}
741 nEKfP=${nEKfP##*/}
743 flag_aFmIG="${PFX_nEKfP}_PROG_ID_FLAG"
745 if [[ -z ${!flag_aFmIG} ]]; then
746 declare -g -x "${flag_aFmIG}=$$"
748 # nEKfP=${nEKfP,,}
749 # shlib_${nEKfP}_init
752 unset nEKfP
753 unset flag_aFmIG
754 } <<<'
756 alias PROG_GVAR_CLR='
758 nEKfP=
759 PFX_nEKfP=
760 flag_aFmIG=
761 func_aFmIG=
763 read -t 1 nEKfP
765 PFX_nEKfP=$(get_vname_pfx "$nEKfP")
766 nEKfP=${nEKfP%%\.*}
767 nEKfP=${nEKfP##*/}
769 flag_aFmIG="${PFX_nEKfP}_PROG_ID_FLAG"
771 unset ${!flag_aFmIG}
773 unset nEKfP
774 unset flag_aFmIG
775 unset func_aFmIG
776 } <<<'
779 # fsyntax: uniqlib
780 # fdesc: the code below let the shlib loading operation only
781 # executing one time.
783 alias uniqlib='
785 nEKfP=
786 PFX_nEKfP=
787 flag_aFmIG=
788 func_aFmIG=
790 read -t 1 nEKfP
792 PFX_nEKfP=$(get_vname_pfx "$nEKfP")
793 nEKfP=${nEKfP%%\.*}
794 nEKfP=${nEKfP##*/}
796 flag_aFmIG="${PFX_nEKfP}_PROG_ID_FLAG"
797 func_aFmIG="$(declare -F shlib_${nEKfP,,}_init)"
799 flag_aFmIG="${PFX_nEKfP}_PROG_ID_FLAG"
800 func_aFmIG="$(declare -F shlib_${nEKfP,,}_init)"
801 if [[ -n ${!flag_aFmIG} && -n $func_aFmIG ]]; then
802 inc_dbgout "uniqlib: return if it has been loaded."
804 unset nEKfP
805 unset flag_aFmIG
806 unset func_aFmIG
807 return 0
810 declare -g -x "${flag_aFmIG}=$$"
812 unset nEKfP
813 unset flag_aFmIG
814 unset func_aFmIG
815 } <<<'
819 # this cmd is an alias cmd. if i use source cmd to include
820 # a shell script file, the global cann't be accessed out
821 # of function. it seems that variable is defined as local
822 # variable in function. at first, include cmd defined as
823 # a script file, and use alias define a wrap cmd like
824 # 'source dsource '. and then, define include cmd all
825 # in alias cmd string.
828 ###########################################################
829 # TBD: add a switch for en/dis loading when it is included.
830 ###########################################################
833 # @ inc => load, load
834 # @ inc => inc, skip
835 # @ load => inc, set inc, skip
836 # @ load => load, skip
838 # different process:
839 # @ inc => load, load
840 # @ inc => inc, inc
841 # @ load => inc, set inc, skip
842 # @ load => load, skip
846 # load operation record different var/func/alias, and set func with -x attr,
847 # but include operation not.
848 # include operation declared -x variables could be used in sub-proc. so,
849 # do not use include in cmdline, it will lead that -x variables does not exist
850 # in load save list.
854 # fsyntax: include <lib-name>
855 # fdesc: include a shlib file unique.
857 # ps:
858 # cannot use stdin as a tty device, the related cmd like stty
859 # can not work in shlib file. because the stdin is redirected
860 # by '<<<'.
862 alias include=" code='
863 xdsource_cnt=
864 xdsource_i=
865 xdsource_lib=
866 xdsource_name=
867 path_list=
869 read -t 1 xdsource_lib
870 # tmp_dbgout \"xdsource_lib=$xdsource_lib\n\"
872 xdsource_name=\$xdsource_lib
874 # set this var before lib_load_prev().
875 last_inc_flag=\$inc_flag
876 if [[ \$inc_flag == load ]]; then
877 inc_dbgout \"include => load\"
878 inc_flag=\"load\"
879 else
880 inc_flag=\"include\"
883 path_list=( \$(echo \$SHLIB_PATH | tr \":\" \" \") )
885 # uniq include judgement.
886 # SHLIB_LIST is LOADING tag list.
887 # SHLIB_INC_LIST is INCLUDing tag list.
888 if [[ \"\$SHLIB_INC_LIST\" =~ \"\${xdsource_lib}\" ]]; then
889 inc_dbgout \"\$xdsource_lib has been included before.\"
890 inc_dbgout \"SHLIB_INC_LIST=\$SHLIB_INC_LIST\"
892 if [[ \$inc_flag == load ]]; then
893 #conflect with included shlib
894 inc_dbgout \"ignore this conflect in nest include shlib by 'load'.\"
897 # restore value.
898 inc_flag=\$last_inc_flag
899 last_inc_flag=\"\"
901 break
903 if [[ \$inc_flag == load && \"\$SHLIB_LIST\" =~ \"\${xdsource_lib}\" ]]; then
904 inc_dbgout \"\$xdsource_lib has been loaded before.\"
905 inc_dbgout \"SHLIB_LIST=\$SHLIB_LIST\"
907 # just invoke shlib_xxx_init() only in PROG_GVAR_INIT().
908 # xdsource_lib=\${xdsource_lib//[^[:alnum:]_]/_}
909 PROG_GVAR_INIT \${xdsource_name,,}
911 # restore value.
912 inc_flag=\$last_inc_flag
913 last_inc_flag=\"\"
915 break
918 if [[ \"\${xdsource_lib:0:1}\" == \"/\" ]]; then
920 elif [[ \"\${xdsource_lib:0:2}\" == \"./\" ]]; then
921 xdsource_lib=\$PWD/\${xdsource_lib}
922 else
923 xdsource_cnt=\${#path_list[@]}
924 for (( xdsource_i=0; xdsource_i < xdsource_cnt; xdsource_i++ )); do
925 # use eval to change path with '~' char to absolutly path.
926 eval path_list[\$xdsource_i]=\"\${path_list[\$xdsource_i]}\"
927 if [[ ! -f \"\${path_list[\$xdsource_i]}/\$xdsource_lib\" ]]; then
928 continue;
930 xdsource_lib=\"\${path_list[\$xdsource_i]}/\$xdsource_lib\";
931 break
932 done
934 if [[ \$xdsource_i == \$xdsource_cnt ]]; then
935 if [[ -f \$PWD/\$xdsource_lib ]]; then
936 xdsource_lib=\"\$PWD/\$xdsource_lib\";
937 else
938 echo -ne \"err: file \$xdsource_lib can not be found in \$SHLIB_PATH\n\" >&2
939 break;
944 lib_load_prev \$xdsource_lib \$inc_flag \$xdsource_name
946 # restore value.
947 inc_flag=\$last_inc_flag
948 last_inc_flag=\"\"
950 unset xdsource_cnt
951 unset xdsource_i
952 unset xdsource_lib
953 unset xdsource_name
956 while true; do
957 eval \"\$code\";
958 break;
959 done;
960 } <<< "
963 # fsyntax: load <lib-name>
964 # fdesc: load a shlib file uniq in cmdline, it could not be sourced
965 # by include cmd. when a shlib is very complex, it should be
966 # load globally to avoid repeated including, to save cpu cost.
968 # ATTENSION:
969 # do not invoke 'load' in command line.
971 alias load=" code='
972 xdsource_cnt=
973 xdsource_i=
974 xdsource_lib=
975 xdsource_name=
976 path_list=
978 read -t 1 xdsource_lib
980 xdsource_name=\$xdsource_lib
982 # set this var before lib_load_prev().
983 last_inc_flag=\$inc_flag
984 inc_flag=\"load\"
986 path_list=( \$(echo \$SHLIB_PATH | tr \":\" \" \") )
988 # SHLIB_LIST is LOADING tag list.
989 # SHLIB_INC_LIST is INCLUDing tag list.
990 # deny after include.
991 if [[ \"\$SHLIB_INC_LIST\" =~ \"\${xdsource_lib}\" ]]; then
992 inc_dbgout \"\$xdsource_lib has been included before.\"
993 inc_dbgout \"it can not be loaded!\"
995 # restore value.
996 inc_flag=\$last_inc_flag
997 last_inc_flag=\"\"
999 break
1001 # uniq include judgement.
1002 if [[ \"\$SHLIB_LIST\" =~ \"\$xdsource_lib\" ]]; then
1003 inc_dbgout \"\$xdsource_lib has been loaded before.\"
1004 inc_dbgout \"execute compact load by invokeding shlib_xxx_init.\"
1005 inc_dbgout \"SHLIB_LIST=\$SHLIB_LIST\"
1007 # restore value.
1008 inc_flag=\$last_inc_flag
1009 last_inc_flag=\"\"
1011 # just invoke shlib_xxx_init() only in PROG_GVAR_INIT().
1012 # xdsource_lib=\${xdsource_lib//[^[:alnum:]_]/_}
1013 PROG_GVAR_INIT \${xdsource_name,,}
1014 break
1017 if [[ \"\${xdsource_lib:0:1}\" == \"/\" ]]; then
1019 elif [[ \"\${xdsource_lib:0:2}\" == \"./\" ]]; then
1020 xdsource_lib=\$PWD/\${xdsource_lib}
1021 else
1022 xdsource_cnt=\${#path_list[@]}
1023 for (( xdsource_i=0; xdsource_i < xdsource_cnt; xdsource_i++ )); do
1024 # use eval to change path with '~' char to absolutly path.
1025 eval path_list[\$xdsource_i]=\"\${path_list[\$xdsource_i]}\"
1026 if [[ ! -f \"\${path_list[\$xdsource_i]}/\$xdsource_lib\" ]]; then
1027 continue;
1029 xdsource_lib=\"\${path_list[\$xdsource_i]}/\$xdsource_lib\";
1030 break
1031 done
1033 if [[ \$xdsource_i == \$xdsource_cnt ]]; then
1034 if [[ -f \$PWD/\$xdsource_lib ]]; then
1035 xdsource_lib=\"\$PWD/\$xdsource_lib\";
1036 else
1037 echo -ne \"err: file \$xdsource_lib can not be found in \$SHLIB_PATH\n\" >&2
1038 break;
1043 lib_load_prev \$xdsource_lib \$inc_flag \$xdsource_name
1045 # restore value.
1046 inc_flag=\$last_inc_flag
1047 last_inc_flag=\"\"
1049 unset xdsource_cnt
1050 unset xdsource_i
1051 unset xdsource_lib
1052 unset xdsource_name
1055 while true; do
1056 eval \"\$code\";
1057 break;
1058 done;
1059 } <<< "
1061 alias unload=" code='
1062 xdsource_cnt=
1063 xdsource_i=
1064 xdsource_lib=
1065 xdsource_name=
1066 path_list=
1068 read -t 1 xdsource_lib
1070 xdsource_name=\$xdsource_lib
1072 inc_dbgout \"unload(\$xdsource_name)\n\"
1074 # set this var before unlib_load_prev().
1075 last_inc_flag=\$inc_flag
1076 inc_flag=\"unload\"
1078 path_list=( \$(echo \$SHLIB_PATH | tr \":\" \" \") )
1080 # SHLIB_LIST is LOADING tag list.
1081 # SHLIB_INC_LIST is INCLUDing tag list.
1082 # deny after include.
1083 if [[ \"\$SHLIB_INC_LIST\" =~ \"\${xdsource_lib}\" ]]; then
1084 inc_dbgout \"\$xdsource_lib has been included before.\"
1085 inc_dbgout \"it can not be unloaded!\"
1087 # restore value.
1088 inc_flag=\$last_inc_flag
1089 last_inc_flag=\"\"
1091 break
1093 # uniq include judgement.
1094 if [[ ! \"\$SHLIB_LIST\" =~ \"\$xdsource_lib\" ]]; then
1095 inc_dbgout \"\$xdsource_lib has not been loaded before.\"
1096 inc_dbgout \"SHLIB_LIST=\$SHLIB_LIST\"
1098 # restore value.
1099 inc_flag=\$last_inc_flag
1100 last_inc_flag=\"\"
1102 break
1105 inc_dbgout \"\$xdsource_lib has been loaded before.\"
1106 inc_dbgout \"execute compact load by invokeding shlib_xxx_init.\"
1108 # skip file existing judgement.
1110 unlib_load_prev \$xdsource_lib \$inc_flag \$xdsource_name
1111 PROG_GVAR_CLR \$xdsource_name
1112 SHLIB_LIST=\"\$(echo \"\${SHLIB_LIST}\" | grep -v \${xdsource_name})\"
1114 # restore value.
1115 inc_flag=\$last_inc_flag
1116 last_inc_flag=\"\"
1118 unset xdsource_cnt
1119 unset xdsource_i
1120 unset xdsource_lib
1121 unset xdsource_name
1124 while true; do
1125 eval \"\$code\";
1126 break;
1127 done;
1128 } <<< "
1131 # fsyntax: reload <lib-name>
1132 # fdesc: load a shlib file uniq in cmdline, it could not be sourced
1133 # by include cmd. when a shlib is very complex, it should be
1134 # load globally to avoid repeated including, to save cpu cost.
1136 # ATTENSION:
1137 # do not invoke 'load' in script code.
1139 alias reload=" code='
1140 xdsource_xxx=
1142 read -t 1 xdsource_xxx
1144 inc_dbgout \"reload(\$xdsource_xxx)\"
1146 unload \$xdsource_xxx
1147 load \$xdsource_xxx
1149 unset xdsource_xxx
1152 while true; do
1153 eval \"\$code\";
1154 break;
1155 done;
1156 } <<< "
1159 ####################################################################################
1162 # shlib info get and set.
1163 # user can use shlibopt to do this work in command line.
1167 # fsyntax: get_shlib_path
1168 # fdesc: get the path list of shlib.
1170 get_shlib_path ()
1172 echo $SHLIB_PATH | tr ':' '
1177 # fsyntax: get_shlib_path_var <var-name>
1178 # fdesc: get the path list of shlib in a variable.
1180 get_shlib_path_in_var ()
1182 local v=$1
1184 [[ -z $1 ]] && return
1186 OLD_IFS=$IFS
1187 IFS=":"
1189 eval "${1}=( $SHLIB_PATH )"
1191 IFS=$OLD_IFS
1195 # fsyntax: set_shlib_path <PATH>
1196 # fdesc: set the shlib path string.
1198 set_shlib_path ()
1200 export SHLIB_PATH="$1"
1202 OLD_IFS=$IFS
1203 IFS=":"
1204 path_list=( $path_list )
1205 IFS=$OLD_IFS
1209 # fsyntax: add_shlib_path <PATH>
1210 # fdesc: append a path string to shlib path.
1212 add_shlib_path ()
1214 local path=$1
1216 [[ $1 =~ ^\./ ]] && path=$PWD/$1
1218 export SHLIB_PATH=$(echo "$SHLIB_PATH:$path" | tr -s ':')
1220 OLD_IFS=$IFS
1221 IFS=":"
1222 path_list+=( $path )
1223 IFS=$OLD_IFS
1227 # fsyntax: del_shlib_path <PATH>
1228 # fdesc: delete the N th path string.
1230 del_shlib_path ()
1232 local tmp
1234 # delete path in SHLIB_PATH.
1235 SHLIB_PATH=$( echo ${SHLIB_PATH[@]//$1/} | tr -s $'\n')
1237 # add eval to expansion operator like '~' to corresponding path.
1238 # so that, $1 use ~ or not does not effect path setting.
1239 tmp=$(eval echo $1)
1240 SHLIB_PATH=$( echo ${SHLIB_PATH[@]//$tmp/} | tr -s $'\n')
1245 ####################################################################################
1248 # fsyntax: prev_include <shlibname>
1249 # fdesc: generate shlib file name with path. generate other paramters
1251 prev_include ()
1253 local cnt=
1254 local i=
1255 local lib=
1256 local name=
1257 local R_LIB_LOAD_LIST=
1258 local R_LIB_INC_LIST=
1259 path_list=
1261 #read -t 1 lib
1262 lib=$1
1263 name=$lib
1265 # set this var before lib_load_prev().
1266 last_inc_flag=$inc_flag
1267 if [[ $inc_flag == load ]]; then
1268 inc_dbgout "include => load"
1269 inc_flag="load"
1270 else
1271 inc_flag="include"
1274 path_list=( $(echo $SHLIB_PATH | tr ":" " ") )
1276 # uniq include judgement.
1277 # SHLIB_LIST is LOADING tag list.
1278 # SHLIB_INC_LIST is INCLUDing tag list.
1279 if [[ "$SHLIB_INC_LIST" =~ "${lib}" ]]; then
1280 inc_dbgout "$lib has been included before."
1281 inc_dbgout "SHLIB_INC_LIST=$SHLIB_INC_LIST"
1283 if [[ $inc_flag == load ]]; then
1284 #conflect with included shlib
1285 inc_dbgout "ignore this conflect in nest include shlib by 'load'."
1288 # restore value.
1289 inc_flag=$last_inc_flag
1290 last_inc_flag=""
1292 break
1294 if [[ $inc_flag == load && "$SHLIB_LIST" =~ "${lib}" ]]; then
1295 inc_dbgout "$lib has been loaded before."
1296 inc_dbgout "SHLIB_LIST=$SHLIB_LIST"
1298 # just invoke shlib_xxx_init() only in PROG_GVAR_INIT().
1299 # lib=${lib//[^[:alnum:]_]/_}
1300 PROG_GVAR_INIT ${name,,}
1302 # restore value.
1303 inc_flag=$last_inc_flag
1304 last_inc_flag=""
1306 break
1309 if [[ "${lib:0:1}" == "/" ]]; then
1311 elif [[ "${lib:0:2}" == "./" ]]; then
1312 lib=$PWD/${lib}
1313 else
1314 cnt=${#path_list[@]}
1315 for (( i=0; i < cnt; i++ )); do
1316 # use eval to change path with '~' char to absolutly path.
1317 eval path_list[$i]="${path_list[$i]}"
1318 if [[ ! -f "${path_list[$i]}/$lib" ]]; then
1319 continue;
1321 lib="${path_list[$i]}/$lib";
1322 break
1323 done
1325 if [[ $i == $cnt ]]; then
1326 if [[ -f $PWD/$lib ]]; then
1327 lib="$PWD/$lib";
1328 else
1329 echo -ne "err: file $lib can not be found in $SHLIB_PATH\n" >&2
1330 break;
1335 #lib_load_prev $lib $inc_flag $name
1336 echo "$lib $inc_flag $name"
1340 # fsyntax: post_include <param-list> <shlibname>
1341 # fdesc:
1343 post_include ()
1345 # restore value.
1346 inc_flag=$last_inc_flag
1347 last_inc_flag=""
1352 # this variable store a function name, which is used to implement features before
1353 # or after source operation.
1355 declare -g shlibwrap_prevcmd=:
1356 declare -g shlibwrap_postcmd=:
1358 alias cmdwrap="{
1359 while true; do
1360 param_BnDfh=""
1361 file_BnDfh=""
1363 # read paramter and invoke wrap cmd.
1364 read -t 1 param_BnDfh
1366 file_BnDfh=\"$(eval \$shlibwrap_prevcmd \$param_BnDfh)\"
1367 [[ -z $file_BnDfh ]] && break;
1369 # break invoking in shlib.
1370 while true; do
1371 source \${file_BnDfh%%\ *}
1372 break;
1373 done
1375 eval \$shlibwrap_postcmd \$file_BnDfh \$param_BnDfh
1377 unset param_BnDfh
1378 unset file_BnDfh
1380 break;
1381 done;
1382 } <<< "
1385 # fsyntax: <load-cmd-name> <lib-name>
1386 # fdesc: lib file including cmd string.
1388 # ps:
1389 # lib name which is used by include cmd, is passed throw stdin redirected by '<<<'.
1390 # but this causes stdin become a pipe, not a tty device. some code invoke 'stty size'
1391 # will return failed, it can not detect stdin as a console.
1393 inc_alias_str=" { \\\`
1394 xdsource_cnt=
1395 xdsource_i=
1396 read -t 1 xdsource_lib
1398 # [[ -z \\\$path_list ]] && \${INC_NAME}_PATH_LIST=( \\\$(echo \\\$\${INC_NAME}_INC_PATH | tr \\\":\\\" \\\" \\\") )
1400 # include file unique
1401 if [[ \\\"\\\$\${INC_NAME}_INC_LIST\\\" =~ \\\"\\\$xdsource_lib\\\" ]]; then
1402 return
1404 echo eval
1405 xdsource_cnt=\\\${#\${INC_NAME}_PATH_LIST[@]}
1406 for (( xdsource_i=0; xdsource_i < xdsource_cnt; xdsource_i++ )); do
1407 if [[ -f \\\${\${INC_NAME}_PATH_LIST[\\\$xdsource_i]}/\\\$xdsource_lib ]]; then
1408 echo \${INC_CMD} \\\\\\\${\${INC_NAME}_PATH_LIST[\\\\\\\$xdsource_i]}/\\\\\\\$xdsource_lib\;
1410 echo [[ \\\\\\\$? == 0 ]] \\&\\& \${INC_NAME}_INC_LIST+=\\\\\\\":\\\\\\\$xdsource_lib\\\\\\\"
1411 break
1413 # echo source \\\${\${INC_NAME}_PATH_LIST[\\\$xdsource_i]}/\\\$xdsource_lib # && return
1414 done
1416 [[ \\\$xdsource_i == \\\$xdsource_cnt ]] && echo -ne \\\"err: file \\\$xdsource_lib can not be found in \\\$\${INC_NAME}_INC_PATH\n\${INC_NAME}_INC_PATH=\\\\\\\"\\\$\${INC_NAME}_INC_PATH\\\\\\\"\n\\\" >&2
1418 unset xdsource_cnt
1419 unset xdsource_i
1420 \\\`; } <<< "
1423 # fsyntax: <unload-cmd-name> <lib-name>
1424 # fdesc: todo: unload is not implemented.
1426 unload_alias_str=" { \\\`
1427 unset xdsource_i
1428 \\\`; } <<< "
1432 # fsyntax: define_include <name> <inc-name> <loadcmd> <unloadcmd> <inc-path>
1433 # fdesc: include feature cmd defination.
1434 define_include ()
1436 local def_path=
1437 local name=${1^^}
1439 def_path=( "$5" )
1440 for (( i=$((${#def_path[@]}-1)); i>=0; i-- )); do
1441 mkdir -p "${def_path}"
1442 done
1444 eval ${name}_INC_PATH="${5}"
1445 eval ${name}_PATH_LIST=\( "$5" \)
1446 INC_NAME=$name
1447 INC_CMD=$3
1448 eval alias ${2}="\"$inc_alias_str\""
1449 unset INC_NAME
1453 # fsyntax: define_load <name> <inc-name> <loadcmd> <unloadcmd> <inc-path>
1454 # fdesc: load feature cmd defination.
1455 define_load ()
1457 local def_path=
1458 local name=${1^^}
1460 def_path=( "$5" )
1461 for (( i=$((${#def_path[@]}-1)); i>=0; i-- )); do
1462 mkdir -p "${def_path}"
1463 done
1465 eval ${name}_INC_PATH="${5}"
1466 eval ${name}_PATH_LIST=\( "$5" \)
1467 INC_NAME=$name
1468 INC_CMD=$3
1469 eval alias ${2}="\"$inc_alias_str\""
1470 unset INC_NAME
1474 ##############################
1475 # section: file tail
1476 ##############################
1482 alias include_bak=" { \` while true; do
1483 xdsource_cnt=
1484 xdsource_i=
1485 read -t 1 xdsource_lib
1487 misc_dbgout nest_level=$nest_level
1489 # [[ -z \$path_list ]] &&
1490 path_list=( \$(echo \$SHLIB_PATH | tr \":\" \" \") )
1492 #echo \"path_list=${path_list[@]}/\\\$xdsource_lib\" >&2
1493 # 不重复包含同一个头文件
1494 if [[ \"\$SHLIB_INC_LIST\" =~ \"\$xdsource_lib\" ]]; then
1495 echo \"\$xdsource_lib has been included before.\" >&2
1496 break
1497 else
1498 echo \"[\$xdsource_lib].\" >&2
1501 echo eval
1502 xdsource_cnt=\${#path_list[@]}
1503 for (( xdsource_i=0; xdsource_i < xdsource_cnt; xdsource_i++ )); do
1504 if [[ -f \"\${path_list[\$xdsource_i]}/\$xdsource_lib\" ]]; then
1505 #echo \"echo [inc] \$xdsource_lib;\"
1506 echo \"get_curr_elem_list \$xdsource_lib; echo ret=\\\\\\$?;\"
1507 echo \"echo \\\"aa \\\$? PID=\\\$\\\$ nest_level=\$nest_level\\\";\"
1508 echo source \\\${path_list[\\\$xdsource_i]}/\\\$xdsource_lib\;
1509 echo \"save_curr_lib_elem_list \$xdsource_lib 1;\"
1510 # echo \"path_list=\\\${path_list[\\\$xdsource_i]}/\\\$xdsource_lib\" >&2
1512 echo [[ \\\$? == 0 ]] \&\& SHLIB_INC_LIST+=\\\":\\\$xdsource_lib\\\"
1513 break
1515 # echo source \${path_list[\$xdsource_i]}/\$xdsource_lib # && return
1516 done
1518 if [[ \$xdsource_i == \$xdsource_cnt ]]; then
1519 if [[ \\\$PWD/\\\$xdsource_lib ]]; then
1520 #echo \"echo \\\"[inc] \$xdsource_lib\\\\\\n;\\\"\"
1521 echo \"eval get_curr_elem_list \$xdsource_lib;\"
1522 echo \"echo \\\"aa \\\$? PID=\\\$\\\$ nest_level=\$nest_level\\\";\"
1523 echo \"source \\\$PWD/\\\$xdsource_lib;\"
1524 echo \"save_curr_lib_elem_list \$xdsource_lib 1;\"
1525 echo [[ \\\$? == 0 ]] \&\& SHLIB_INC_LIST+=\\\":\\\$xdsource_lib\\\"
1526 else
1527 echo -ne \"err: file \$xdsource_lib can not be found in \$SHLIB_PATH\n\$SHLIB_PATH=\\\"\$SHLIB_PATH\\\"\n\" >&2
1531 unset xdsource_cnt
1532 unset xdsource_i
1533 break
1535 done
1537 misc_dbgout z nest_level=\$nest_level;
1538 nest_level=$((nest_level+1))
1539 misc_dbgout z nest_level=\$nest_level;
1540 } <<< "
1542 alias unload_bak=" { \` while true; do
1543 xdsource_cnt=
1544 xdsource_i=
1545 xdsource_fun=
1547 read -t 1 xdsource_lib
1549 # [[ -z \$path_list ]] &&
1550 path_list=( \$(echo \$SHLIB_PATH | tr \":\" \" \") )
1552 #echo \"path_list=${path_list[@]}/\\\$xdsource_lib\" >&2
1553 # 不重复包含同一个头文件
1554 if [[ \"\$SHLIB_LIST\" =~ \"\$xdsource_lib\" ]]; then
1555 echo \"\$xdsource_lib has been included before.\" >&2
1556 break
1557 else
1558 echo \"[\$xdsource_lib].\" >&2
1561 echo eval
1562 xdsource_cnt=\${#xdsource_fun[@]}
1563 for (( xdsource_i=0; xdsource_i < xdsource_cnt; xdsource_i++ )); do
1564 echo \"unset \"
1565 if [[ -f \"\${xdsource_fun[\$xdsource_i]}/\$xdsource_lib\" ]]; then
1566 #echo \"echo [inc] \$xdsource_lib;\"
1567 echo \"get_curr_elem_list \$xdsource_lib; echo ret=\\\\\\$?;\"
1568 echo source \\\${xdsource_fun[\\\$xdsource_i]}/\\\$xdsource_lib\;
1569 echo \"save_curr_lib_elem_list \$xdsource_lib 1;\"
1570 # echo \"xdsource_fun=\\\${xdsource_fun[\\\$xdsource_i]}/\\\$xdsource_lib\" >&2
1572 echo [[ \\\$? == 0 ]] \&\& SHLIB_LIST+=\\\":\\\$xdsource_lib\\\"
1573 break
1575 # echo source \${xdsource_fun[\$xdsource_i]}/\$xdsource_lib # && return
1576 done
1578 if [[ \$xdsource_i == \$xdsource_cnt ]]; then
1579 if [[ \\\$PWD/\\\$xdsource_lib ]]; then
1580 #echo \"echo \\\"[inc] \$xdsource_lib\\\\\\n;\\\"\"
1581 echo \"eval get_curr_elem_list \$xdsource_lib;\"
1582 echo \"source \\\$PWD/\\\$xdsource_lib;\"
1583 echo \"save_curr_lib_elem_list \$xdsource_lib 1;\"
1584 echo [[ \\\$? == 0 ]] \&\& SHLIB_LIST+=\\\":\\\$xdsource_lib\\\"
1585 else
1586 echo -ne \"err: file \$xdsource_lib can not be found in \$SHLIB_PATH\n\$SHLIB_PATH=\\\"\$SHLIB_PATH\\\"\n\" >&2
1590 unset xdsource_cnt
1591 unset xdsource_i
1592 break
1594 done
1595 \`; } <<< "
1598 # reload shlib when code is updated.
1600 alias reloadshlib_bak=" { \` while true; do
1601 xdsource_cnt=
1602 xdsource_i=
1603 read -t 1 xdsource_lib
1605 # [[ -z \$path_list ]] &&
1606 path_list=( \$(echo \$SHLIB_PATH | tr \":\" \" \") )
1608 #echo \"path_list=${path_list[@]}/\\\$xdsource_lib\" >&2
1610 echo eval
1611 xdsource_cnt=\${#path_list[@]}
1612 for (( xdsource_i=0; xdsource_i < xdsource_cnt; xdsource_i++ )); do
1613 if [[ -f \${path_list[\$xdsource_i]}/\$xdsource_lib ]]; then
1614 echo source \\\${path_list[\\\$xdsource_i]}/\\\$xdsource_lib\;
1615 # echo \"path_list=\\\${path_list[\\\$xdsource_i]}/\\\$xdsource_lib\" >&2
1617 echo [[ \\\$? == 0 ]] \&\& SHLIB_LIST+=\\\":\\\$xdsource_lib\\\"
1618 break
1620 # echo source \${path_list[\$xdsource_i]}/\$xdsource_lib # && return
1621 done
1623 [[ \$xdsource_i == \$xdsource_cnt ]] && echo -ne \"err: file \$xdsource_lib can not be found in \$SHLIB_PATH\n\$SHLIB_PATH=\\\"\$SHLIB_PATH\\\"\n\" >&2
1625 unset xdsource_cnt
1626 unset xdsource_i
1627 break
1629 done \`; } <<< "
1632 # todo:
1633 # those code below, is reserved for shlib unload
1637 # fsyntax: uniqlib [<lib-name>]
1638 # fdesc: it used in shlib to let the code load unique, and others will be
1639 # running every time.
1641 alias uniqlib_bak="
1643 [[ -n \`eval eval echo \\\\\\\${__SHLIB_\\\$(basename \${BASH_SOURCE//./_})__}\` ]] && echo \"included 2nd .\" && return
1644 declare -g __SHLIB_\`basename \${BASH_SOURCE//./_}\`__=1
1645 eval ENV_SHLIB_\`basename \${BASH_SOURCE//./_}\`=\\\"\$(env)\\\"
1646 eval \"ALIAS_SHLIB_\`basename \${BASH_SOURCE//./_}\`=( \\\"\${!BASH_ALIASES[@]}\\\" )\"
1647 eval FUNC_SHLIB_\`basename \${BASH_SOURCE//./_}\`=\\\"\$(declare -F)\\\"
1652 # fsyntax: libend
1653 # fdesc: use with uniqlib at the end of uniq-block.
1655 alias libend="
1656 # declare -g __SHLIB_\`basename \${BASH_SOURCE//./_}\`_TMP__=1
1657 eval ENV_SHLIB_\`basename \${BASH_SOURCE//./_}\`_TMP=\\\"\$(env)\\\"
1658 declare -g ALIAS_SHLIB_\`basename \${BASH_SOURCE//./_}\`_TMP=( \"\${!BASH_ALIASES[@]}\" )
1659 eval FUNC_SHLIB_\`basename \${BASH_SOURCE//./_}\`_TMP=\\\"\$(declare -F)\\\"
1661 #eval ENV_SHLIB_\`basename \${BASH_SOURCE//./_}\`=get_var_txt_appended ENV_SHLIB_\`basename \${BASH_SOURCE//./_}\` ENV_SHLIB_\`basename \${BASH_SOURCE//./_}\`_TMP
1662 eval echo list=\\\"\\\${ENV_SHLIB_\`basename \${BASH_SOURCE//./_}\`}\\\"
1664 #declare -F