improve of cmpl.
[bush.git] / tools / cmpl / shlib / incfile.shlib
blobc474cb2bd5c87fc0ed59ac86ca7e5773e0a9707d
2 __get_file_top_valid_id ()
4         local i
5         
6         i=$(ulimit -n)
7         for (( i=$((i-1)); i>0; i-- )); do
8 #               echo i=$i >&2
9                 [[ ! -e /proc/self/fd/$i ]] && echo $i && return
10         done
13         f_ttyout=$(ps -p $$ -o tty | tail -n 1 | cut -d ' ' -f1)
14 #       echo -ne "f_ttyout=$f_ttyout\n"
15         f_ttyout="/dev/$f_ttyout"
17         vch_ttyout=$(__get_file_top_valid_id)
18 #       echo f_ttyout=$f_ttyout
19         eval "exec $vch_ttyout<>$f_ttyout"
20         [[ $? != 0 ]] && vch_ttyout=1
22 pause ()
24         echo -ne "$2" >&$vch_ttyout
25         
26         [[ -z "$1" ]] && echo "please specify parameter for apuse()." && return
28         if [[ -n $3 && $DEF_INPUT == "true" ]]; then
29                 eval $1="\"\$3\""
30         else
31                 OLD_IFS=$IFS
32                 IFS=$'\n'
33                 read -u $vch_ttyout -r $1
34                 IFS=$OLD_IFS
35                 [[ -n $3 ]] && [[ -z ${!1} || ${!1} == "$'\n'" ]] && eval "$1=$3"
36         fi
40 # return if has been sourced before.
41 # this code is disabled, it should be putted in application program.
43 #alias include >/dev/null 2>&1
44 #[[ $? == 0 ]] && alias inc="include" return
46         
47 # TBD: write value in tmp, it should be generated by _EVL
48 #       SRCPKG_DIR_FULL=$PWD
51 shopt -s expand_aliases
52 alias include="diffinc "
55 inc_info ()
57         echo "$1" | grep -E "inc_info" >/dev/null 2>&1
58         test "$?" != 0 && return
59         
60         echo -ne "$@" # "\n"
63 inc_lvl=0
65 inc_indent_info ()
67         local cnt=$inc_lvl
69         echo "$1" | grep -E "inc_info" >/dev/null 2>&1
70         test "$?" != 0 && return
72         # for debugging.
73         while [[ $cnt -gt 0 ]]; do
74                 inc_info "  "
75                 : $((cnt--))
76         done
77         echo -ne "inc ($1)\n"
80 inc_dbgout ()
82         echo "$1" | grep -E "inc_dbgout" >/dev/null 2>&1
83         test "$?" != 0 && return
84         echo -ne "$@" # "\n"
87 #alias inc="diffinc "
88 #incfile ()
90 # if source file direct nestly, the sub file source path is not correct.
91 # use this alias cmd to fix this problem.
92 # it stores $PWD, entering dir of include file.
94 inc ()
96         local pwd=$PWD
97         local vname=
99         [[ -z "$1" || ! -f "$1" ]] && return
100         
101         inc_indent_info
102         
103         # uniq load
104         vname="`basename $1`"
105         vname=`echo "$vname" | tr '[[:punct:]]' '_' | tr '[[:lower:]]' '[[:upper:]]'`
107         # XXX: redundent include check will causes parameter can not be updated.
108 #       eval test \"\$$vname\" = 1 && return
109         eval $vname=1
110         
111 #       echo inc $1
112         : $((inc_lvl++))
114         cd $(dirname $1)
115         source $(basename $1)
116         cd $pwd
117         
118         : $((inc_lvl--))
121 # get func list in current process.
122 get_func_list ()
124         local data=
126         while read data; do
127                 data="${data##* }"
128                 echo -ne "${data}\n"
129         done << EOF
130 `declare -F`
134 # get var list in current process.
135 get_var_list ()
137         local data=
138         
139         while read data; do
140                 data="${data%%=*}"
141                 data="${data##* }"
142                 echo "${data}"
143         done << EOF
144 `declare -p | grep -e "declare" | sed -e "s/^.*-f.*$//g"`
148 # get alias list in current process.
149 get_alias_list ()
151         local data=
152         
153         while read data; do
154                 echo "${data}"
155         done << EOF
156 `alias | grep -e "^alias"`
161 # fsyntax: list_diff <type> <name>
162 #          <outputvarname> = <listvarname1> - <listvarname2>
163 # fdesc: type is one of func/var/alias, name is shlib.
165 list_diff ()
167         local vname="$2"
168         local list_name=
169         local list2_name=
170         local data=
172                 list_name="${1}list1_$vname"
173                 list2_name="${1}list2_$vname"
174 #               unset $list2_name
175                 export $list2_name=""
176 #               echo "$list2_name define:"
177 #               declare -p $list2_name
179                 # diff with the list saved before source operation.
180                 while read data; do
181 #                       data="${data##* }"
182 #                       data="${data#*< }"
183                         data="$(echo "{data}" | sed -E "s/[[:blank:]]*< //g")"
184                         if [[ "$1" == func ]]; then
185                                 # add -x option to function, so that sub-proc can use it without load again.
186                                 declare -f -x ${data}
187                         elif [[ "$1" == var ]]; then
188                                 if [[ "$data" =~ 'funclist' || "$data" =~ 'varlist' || "$data" =~ 'aliaslist' ]]; then
189                                         continue
190                                 fi
191                         elif [[ "$1" == alias ]]; then
192                                 data="${data%%=*}"
193                                 data="${data##*alias }"
194                         fi
195                         # save to array.
196                         eval $list2_name+="\"${data} \""
197                 done < <(echo "${!list_name}" | diff --from-file=<(get_$1_list) - | grep -e "<")
198                 
199                 # ctx_xxx, just for alias recovery.
200                 [[ "$1" == alias ]] && eval ctx_$list2_name="\$(alias \${$list2_name})"
202                 unset $list_name
203                 eval list_dbgout \"\${$list2_name[@]}\" | tr  ' ' $'\n'
207 # syntax: var_list_diff <outputvarname> = <listvarname1> - <listvarname2>
208 # desc: it diff two variable data, and get the new appended info.
210 listvar_diff ()
212     local vout=$1
213     local vin1="$3"
214     local vin2="$5"
215     local data=
216     
217     if test -n "$1" && test -n "$3" && test -n "$5" && test "$2" = '=' && test "$4" = '-' ; then
218         eval $1=\"\"
219         eval "$3=\"$(echo "${!3}" | tr ' ' $'\n')\""
220         eval "$5=\"$(eval echo \"\${$5}\" | tr ' ' $'\n')\""
221 #        echo "${!5}"
222 #        echo "${!3}"
223         while read data; do
224             data=${data#< }
225             # save to array.
226             eval $1=\"\${$1}${data}\"\$'\n'
227         done << EOF
228 `echo "${!5}" | diff --from-file=<(echo "${!3}") - | grep -e "<";`
230         eval $1="$(eval echo \"\${$1}\" | sed -E "/^\$/d")"
231     fi
234 diffinc ()
236         local vname=$(basename $1)
237         vname="$(echo "${vname}" | sed -E "s/[.]([[:alnum:]_]*)//g; s/[^[:alnum:]_]/_/g")"
239         #
240         # declare var before source, or it will be append to varlist_xxx.
241         #
242         eval funclist1_$vname=""
243         eval funclist2_$vname=""
244         eval varlist1_$vname=""
245         eval varlist2_$vname=""
246         eval aliaslist1_$vname=""
247         eval aliaslist2_$vname=""
248         
249         #
250         # getting func/var/alias list before
251         #
252         eval funclist1_$vname=\"\$\(get_func_list\)\"
253         eval varlist1_$vname=\"\$\(get_var_list\)\"
254         eval aliaslist1_$vname=\"\$\(get_alias_list\)\"
255         
256         #
257         # file source.
258         #
259 #       echo include $1
260         inc $1
261         
262         #
263         # getting func/var/alias list after
264         #
265         eval funclist2_$vname=\"\$\(get_func_list\)\"
266         eval varlist2_$vname=\"\$\(get_var_list\)\"
267         eval aliaslist2_$vname=\"\$\(get_alias_list\)\"
268         
269         #
270         # diff list between before and after.
271         #
272         listvar_diff funclist_$vname = funclist2_$vname - funclist1_$vname
273         listvar_diff varlist_$vname = varlist2_$vname - varlist1_$vname
274         listvar_diff aliaslist_$vname = aliaslist2_$vname - aliaslist1_$vname
275         
276         # for func list
277 #       list_diff func $vname
278         # for var list
279 #       list_diff var $vname
280         # for alias list
281 #       list_diff alias $vname
282         
283 #       declare -p funclist_$vname varlist_$vname aliaslist_$vname
285 #       eval echo funclist_$vname=\${funclist_$vname} > 3.txt
286 #       eval echo varlist_$vname=\${varlist_$vname} >> 3.txt
287 #       eval echo aliaslist_$vname=\${aliaslist_$vname} >> 3.txt
292 # line data
294 imilinedata=
295 imicmdlist='
297 loadimi
298 loadlist
299 return
300 sourceimi
303 imivname=
304 imivopr=
305 imivvalue=
307 imicmd=
308 imicmdopt=
310 on_imi_set_var=
312 imi_set_var ()
314         test -n "$on_imi_set_var" && 
315                 $on_imi_set_var "$imivname" "$imiopr" "$imivalstr" &&
316                 test $? != 0 && 
317                 IMICMNT= &&
318                 return
320         [[ "$LOAD_DBG" = 1 ]] && echo $1 "$imivname" "$imiopr" "$imivalstr"
321         $1 "$imivname" "$imiopr" "$imivalstr"
323         imivlist="$imivlist"$'\n'"${imivname}"
325 #       echo "#########################################"
326 #       echo -n "${imivname}="
327 #       envar ${imivname}
328 #       echo 
330         if test "$(echo ${imivname} | tail -c -5)" = _EVL; then
331                 imivname="$(echo ${imivname} | head -c -5)"
332                 eval eval "$imivname=\"\\\"\${${imivname}_EVL}\\\"\""
333                 imivlist="$imivlist"$'\n'"${imivname}"
334         fi
335         
336         IMICMNT=
340 # NOTE:
341 # @ init with "" string, ' in it should add like '\'', as it is in '' string.
342 # @ do not add comment after assignment, especially after "" or '' or ().
343 # @ ${XXX:1:2}, envar opr like slice and others are not supported.
347 # fsyntax: loadimi <imi-file-name>
349 __loadimi ()
351         local cnt=$inc_lvl
352         local pwd=$PWD
353         local file=$(basename $1)
354         
355         imivlist=""
357         # valid checking.
358         test -z "$1" || test ! -f "$1" && inc_dbgout "invalid file($1).\n" && return
359         
360 #       test "`echo "$1" | grep -o -P '([^\.]*)' | tail -n 1`" != "imi" && echo "[error]: specified file $1 is not .imi file.\n" >&2 && unset $name && return 1
362         # for debug info.
363         while test "$cnt" -gt 0 ; do
364                 inc_info "  "
365                 : $((cnt--))
366         done
367         inc_info -ne "loadimi ($@)\n"
368         
369         : $((inc_lvl++))
370         
371         cd $(dirname $1)
373         if test ! -e "$file" ; then
374                 echo "list file '$1' is not exist.\n" >&2
375         fi
377         {
378                 # directly source if no interpreter loadimi setted.
379                 read -r imilinedata
380                 if strstr ! "$imilinedata" =~ 'loadimi'; then
381                         test "$LOAD_DBG" = 1 && set -x
382                         source $file
383                         set +x
385                         cd $pwd
386                         : $((inc_lvl--))
387                         unset LOAD_DBG
388                         return
389                 fi
391 #               echo "loadimi ($file)"
393                 # it need -r param to receive '\'.
394                 while read -r imilinedata; do
395                         : $(( i++ ))
396                         
397                         #
398                         # line string proc
399                         #
400                         envar_name_parsing || continue
401 #                       declare -p imilinedata imicmd imicmdopt imivname imiopr imivalpfx imivalstr imivalsfx
402 #                       pause "testvar" "envar_name_parsing:" ""
403                         
404                         #
405                         # check cmd
406                         #
407                         test -n "$imicmd" && echo "$imicmdlist" | grep -q -E "$imicmd" && 
408                                 eval "$imicmd \"$imicmdopt\" \"$imivname\" \"$imiopr\" \"$imivalstr\"" &&
409                                 continue
410                         
411                         test -z "$imiopr" && 
412                                 { eval $imilinedata ; continue; }
413 #                               echo -e "\033[1m\033[31m[error][$file:line$i]\033[0m: '$imilinedata' not a valid assign statement." && 
414 #                               exit -1
415                         
416                         #
417                         # load multiple line data init. set if it is an array init.
418                         #
419                         load_var_string && imi_set_var loadenv && continue
420                         imi_set_var loadarr
421                 done
422         } < "$file"
423         
424         imivlist="$(echo "$imivlist" | uniq)"
426         cd $pwd
427         
428         : $((inc_lvl--))
429         unset LOAD_DBG on_imi_set_var
433 # fdesc: load imi by cmd of 'source', to decrease cpu cost.
434 #        it's for parameter without array.
436 sourceimi ()
438         local cnt=$inc_lvl
440         local vlist=
441         local pwd=$PWD
442         local file=$(basename $1)
444         # valid checking.
445         test -z "$1" || test ! -f "$1" && inc_dbgout "invalid file($1).\n" && return
446         test "`echo "$1" | grep -o -P '([^\.]*)' | tail -n 1`" != "imi" && 
447                 echo "specified file $1 is not a valid .imi file.\n" >&2 && 
448                 return 1
449         
450         # for debug info.
451         while test "$cnt" -gt 0 ; do
452                 inc_info "  "
453                 : $((cnt--))
454         done
455         inc_info "loadimi ($@)\n"
457         : $((inc_lvl++))
458         cd $(dirname $1)
460         source $file
462         cd $pwd
463         : $((inc_lvl--))
467 # fdesc: load imi by cmd of 'source', to decrease cpu cost.
468 #        it's for parameter without array.
470 loadlist ()
472         local cnt=$inc_lvl
474         local vlist=
475         local pwd=$PWD
476         local file=$(basename $1)
477         local vname=
479         # valid checking.
480         test -z "$1" || test ! -f "$1" && inc_dbgout "invalid file($1).\n" && return
481         test "`echo "$1" | grep -o -P '([^\.]*)' | tail -n 1`" != "list" && 
482                 echo "specified file $1 is not a valid .list file.\n" >&2 && 
483                 return 1
484         
485         vname="$(echo "$file" | tr '[[:lower:]]' '[[:upper:]]' | tr '[^[:punct:]_]' '_')_Y"
486         
487         # for debug info.
488         while test "$cnt" -gt 0 ; do
489                 inc_info "  "
490                 : $((cnt--))
491         done
492         inc_info "loadimi ($@)\n"
494         : $((inc_lvl++))
495         cd $(dirname $1)
496         
497         # load without comment.
498         eval ${vname}="\"$(cat $file | sed -E "s/[[:blank:]]*([#].*)?[\r]?$//g; /^$/d; s/\\\\/\\\\\\\\/g; s/[\"]/\\\\\"/g;")\""
500         # TBD: store them into arr?
502         cd $pwd
503         : $((inc_lvl--))
506 # put this code into porting.shlib
507 STDSH=1
508 #test "$SHELL" = '/bin/bash' && STDSH=
510 # use __loadimi in standard shell
511 if [[ -n "$STDSH" ]]; then
512         alias loadimi=__loadimi
513 elif [[ false ]]; then
514         :
515 else
516         alias loadimi=sourceimi