#!/bin/sh
cat << 'EEE' > /dev/null
/* fnf .... find file, find parser
 * Copyright (C) 2017-2019 Momi-g
 *
 * This program 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.
 *
 * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
 */
EEE

#	cmd='-h	bool 0
#	     -r	int	-1	
#	     -o	bool 0'
#	buf=`prsopt "$cmd"`
#	eval "$buf"
#	if [ $? -ne 0 ] ; then echo "$0: optErr. $OPTARG" >/dev/stderr ; exit 1; fi
#	

func_rdopt() {
	(
rdopt_fmt="$1"	#	":ab:c"	etc. format.
shift

#ck quiet mode
rdopt_quiet=1
rdopt_buf=${rdopt_fmt%%[!:]*}
if [ "$rdopt_buf" != ':' ] ; then
	rdopt_quiet=0
	rdopt_fmt=':'"$rdopt_fmt"
fi

#--inicialize	make list opt_a='', ...

#ab:c -> 'a' \n 'b' \n 'c' \n
rdopt_buf='s/://g
s/./&\
/g'
rdopt_zerolist=`echo "$rdopt_fmt" | sed -e "$rdopt_buf" | sed -e "
/^$/d
s/^/opt_/g
s/$/=''/g
" `

#--- local vars
# rdopt_fmt="$1"	#	":ab:c"		opt format
# rdopt_quiet=1
# rdopt_zerolist=`echo "$rdopt_fmt" | sed -e "$rdopt_buf" | sed -e "
# rdopt_buf='s/://g

rdopt_out=""
rdopt_opt=""
rdopt_skip=""
rdopt_err=""

rdopt_safe="
s#'#'\"'\"'#g
1 s/^/'/g
$ s/$/'/g"

#---getopts loop. break if all args read or detect '--'
while :
do
if [ 0 -eq "$#" ] || [ "$rdopt_err" = "1" ] ; then
	break
fi
if [ "$1" = "--" ] ; then
	shift ; break
fi

getopts "$rdopt_fmt" rdopt_opt "$@"	# ":a:bc:f:" etc...
# err detect@silent mode
# $?=1 ... detect optend or '--'. '--' is removed at previous line.
# ':' ... detect option, but dont have subargs (OPTARG="factor").
# '?' ... detect unsupported option char (OPTARG="factor") or args end (OPTARG="blank").
# OPTARG ... "" is optend. "a/b/c..." is invalid option 
# OPTIND ... if err, OPTIND indicates next (new) arg pos. 

if [ "$?" = "1" ] ; then 		# normal end (detect normal args). save general args.
	shift $((OPTIND - 1))
	if [ "$#" -eq "0" ] ; then
		break
	fi
	# new set make
	rdopt_buf=`printf '%s' "$1" | sed -e "$rdopt_safe"`
	rdopt_skip="$rdopt_skip $rdopt_buf"
	shift
	OPTIND=1
	continue
fi

if [ "$rdopt_opt" = "?" ] || [ "$rdopt_opt" = ":" ] ; then 	# detect invalid opt
	rdopt_err=1		#OPTARG has err option char.
	continue
fi

# normal. detect option.
if [ "$OPTARG" = "" ] ; then	# no subargs 
	rdopt_out="$rdopt_out
opt_$rdopt_opt"'=1'
else	# exist subargs 
rdopt_buf=`printf "%s\n" "$OPTARG" | sed -e "$rdopt_safe" `
	rdopt_out="$rdopt_out
opt_$rdopt_opt"'='"$rdopt_buf"
fi
done
# exit parse

if [ "$rdopt_err" = "1" ] ; then
	if [ "$rdopt_quiet" = "0" ] ; then
		rdopt_buf=${0##*/}
		echo "$rdopt_buf: invalid option. sleep. ( $OPTARG )" >/dev/stderr
		while :
		do
			sleep 1000
		done
	else
		rdopt_out="OPTARG=$OPTARG
OPTIND=1
test 1 = 0"
	fi
else

#	'--' end
	if [ "$#" != "0" ] ; then
	rdopt_buf=`cat << 'EEE'
for ii
do
	printf '%s' "$ii" | sed -e "
s#'#'\"'\"'#g
1 s/^/'/g
$ s/$/' /g"
done 
EEE
`
	rdopt_buf=`eval "$rdopt_buf"`
	rdopt_skip="$rdopt_skip $rdopt_buf"
	fi

	rdopt_out="OPTIND=1

$rdopt_zerolist
$rdopt_out
set -- $rdopt_skip
"
fi



printf '%s\n' "$rdopt_out"

# clean
OPTIND=1
rdopt_fmt=""
rdopt_quiet=""
rdopt_zerolist=""
rdopt_buf=""

rdopt_out=""
rdopt_opt=""
rdopt_skip=""
rdopt_err=""
rdopt_safe=""
)
OPTIND=1
}





buf=`func_rdopt "hr:oP" "$@"`
eval "$buf"
if [ $? -ne 0 ] ; then echo "$0: optErr. $OPTARG" >/dev/stderr ; exit 1; fi

if [ "$opt_h" = '1' ] ; then
cat << 'EEE'
HowTo (find file/directry)
option: -h(elp), -r(ecurse -1(dfl),0,1,2..), -o(ctal output)
------
ex.) ~$ fnf txt unko (-r -1)	#search files from ./ 
>>> ./unko___uh.txt	
    ./unko.txt
    ./unkotxt/
...show include 'txt' + 'unko' (fixed)string in filepath (not file name)
...recursive search (-1:non stop 0:pwd 1:pwd+next)
...directry(or directry link) is end with '/'.

ex.) ~$ fnf '/u' unko //uh
>>>	./unko.txt	>>>	'//' means 'not'. '/u' && 'unko' && !'uh'
... normal filepath probably should not contain '//'.	(./aaa//bbb/c.txt etc)

ex.) ~$ fnf txt unko -o
>>>	\001\004\123...	>>> printf '\001\004\123...'  ->  ./unko___uh.txt
	\111\333...
... output in octal number. You can safely handle filenames containing
 newlines and unicode characters. ("./aaa/bb\n\n\123  b/ccc.txt" etc)
EEE
exit 0
fi

#	-P縺ョ繝�ヵ繧ゥ縺ァ譎ョ騾壹↓max縺、縺代※讀懃エ「縲Uype l縺ァ繧キ繝ウ繝懊Μ繝�け繝ェ繝ウ繧ッ繧呈爾縺怜�縺励※鬆ュ縺ォ//0縺ソ縺溘>縺ェ
#	繝輔Λ繧ー繧偵▽縺代※蜀肴、懃エ「縺輔○繧九→縺九€Naxdepth縺御スソ縺医�繝シ縲ょセョ螯吶□縲らャャ荳€髫主ア、縲∫ャャ莠碁嚴螻、縺」縺ヲ諢溘§縺ォ
#	讀懃エ「縺輔○縺ヲ繧ケ繝ゥ繝�す繝・繧ォ繧ヲ繝ウ繝�purne縺ァ縺カ縺」縺。縺弱k縺ィ縺九€Moop蟇セ遲悶′縺ゥ繝シ繧茨シ�
#	find縺ッ繝代ち繝シ繝ウ縺後す繧ァ繝ォ繝代ち繝シ繝ウ縺ェ縺ョ縺ァ縲√◎縺ョ縺ク繧薙b縲�-path縺ァ繝代せ蛛・菴懊↓縺ェ繧�
#	find . -path ./src/emacs -prune -o -print
#	find縺ッ遒コ蝗コ,-o -a縺ィ蜷ヲ螳壹�縺ソ隕冗ィ九€�
#	find . -path '*/*/*' -prune



find -print0 --version >/dev/null 2>&1
if [ "$?" = "0" ] && [ "$opt_P" != "1" ]; then
	echo "// (stderr info) detect gnu-find. use fastmode." >/dev/stderr
	gnumode=1
fi


if [ "$opt_r" != "-1" ] && [ "$opt_r" != "" ] ; then
	ptn='*/*/*'		#>> pwd縺ッ/荳€縺、縺�縺代€�//縺ッ繧オ繝悶ョ繧」繝ャ繧ッ繝医Μ縲�///縺ッ繧オ繝悶し繝悶€�
	for ii in `seq 1 $opt_r `
	do
		ptn="$ptn"'/*'
	done
else
	ptn='*//*'	# 蝓コ譛ャ逧�↓//繧貞性繧€繝輔ぃ繧、繝ォ縺ッ蟄伜惠縺怜セ励↑縺�€ゅヵ繧。繧、繝ォ蜷阪↓\000縺ィ/縺ッ菴ソ縺医↑縺�◆繧√€�
#	null_hit縺ァ譫晏�繧翫r髦イ縺舌€�
fi
# maxdepth縺掲ind縺ァ菴ソ縺医↑縺��縺ァ莉」譖ソ縲Qosix.

outstr='cat -'
if [ "$opt_o" != "1" ] ; then
	outstr='while read -r aa
do
	printf "$aa"
	echo
done'
fi
#	syscall繧ェ繝シ繝舌�繝倥ャ繝峨′驥阪>縺代←縲∥wk縺ィ縺菊val菴ソ縺医↑縺�@縲�%b繧ゅす繧ァ繝ォ縺�縺代□縺励€�
#	printf閾ェ菴薙�built-in縺�縺九i縲∬�蜻ス逧�↓驕�>
#	縺」縺ヲ縺サ縺ゥ縺倥c縺ェ縺�€Bwk縺ォ豈斐∋縺溘i500%繝励Λ繧ケ縺」縺ヲ縺ィ縺薙€� awk 10ms -> while print 50ms


# 20ms






# 蝗コ螳壽枚蟄玲、懃エ「縺ョ縺ソ縺ォ邨槭k縲よ、懃エ「譁�ュ励b逕溘□縺ィ謇ア縺�↓縺上>縺ョ縺ァ8騾イ縺ォ縺励→縺上€�
buf=`for ii in "$@"
do
	printf '%s\000' "$ii"
done | od -An -to1 -w16 -v | tr -d '\n' | sed -e 's# 000#@#g' | tr ' ' 'o' | tr '@' '\n' `

filter=""
for ii in $buf
do
	buf=${ii#o057o057}	# //bbb 縺ソ縺溘>縺ェ'//'莉倥″譁�ュ怜�縺ッ蜷ヲ螳壹€Oot.
	if [ "$buf" != "$ii" ] ; then
		filter="$filter
/$buf/ d"
	else
		filter="$filter
/$buf/ ! d"
	fi
done
filter="sed -e '$filter'"
# echo "$filter"
# exit

#	sed -e '
#	/o141o141/ ! d
#	/o163o163/ ! d
#	/o144o144/ d'

#	sed -e ''


# ---main
# -L縺ッtype縺ァ繝輔か繝ォ繝€邉サ縺ョ陦ィ遉コ縺ョ蟆サ蟆セ縺ォ/繧貞愛蛻・縺吶k縺ィ縺阪€‥ir繝ェ繝ウ繧ッ譎ゅ↓諠��ア縺梧ャイ縺励>縺ョ縺ァ縲�
# . 縺ィ./縺ァ豺キ蝨ィ縺励※繧九€ょ、峨€Ms縺ッ--indi縺ァ/謖�ョ壹〒縺阪k縺代←縲’ind縺ォ縺ッ縺ェ縺�€�
# -L ./ 縺ィ -L .縺ァ驕輔≧縲ゅヰ繧ー縺」縺ヲ縺サ縺ゥ縺倥c縺ェ縺�¢縺ゥ豕ィ諢上′蠢�ヲ√€�
# echo "$ptn"
# exit

# -exec縺碁≦縺�∩縺溘>縲�20ms -> 800ms

# 20ms time find -L ./ -path "@@" -prune -o -print
# 700ms time find -L ./ -path "@@" -prune -o -exec printf '%s\n' '{}' ';'
# syscall縺碁≦縺�°繧�//繧剃スソ縺」縺ヲ菴輔→縺九〒縺阪s縺九€�...辟。逅�€ょ�蜉帙☆繧区婿豕輔′縺ェ縺�€�
# exec縺ァ縺セ縺ィ繧√i繧後※縺励∪縺」縺ヲ繧九€Hnu縺ィ繧ケ繧、繝�メ縺九↑縲�


# gnu can use -printf ... fast output(40ms)
if [ "$gnumode" = "1" ] ; then
	cmd=`cat << 'EEE'
find -L ./ -path "$ptn" -prune \
-o -type d -a '!' -path '*/' -a -printf '%p/\000' \
-o -printf '%p\000'
EEE
`

else	# posix & syscall. slow. 800ms
	cmd=`cat << 'EEE'
find -L ./ -path "$ptn" -prune \
-o -type d -a '!' -path '*/' -a -exec printf '%s/\000' '{}' ';' \
-o -exec printf '%s\000' '{}' ';'
EEE
`

fi


eval "$cmd" |
	od -An -to1 -w16 -v | sed -e 's# 000#@#g' | tr -d '\n' | 
	tr ' ' 'o' | tr '@' '\n' | eval "$filter" | tr 'o' '\134' | eval "$outstr"

#	. 繝代せ縺九i謗「縺怜�縺励◆荳€縺、荳€縺、縺ョ繝輔ぃ繧、繝ォ縺ォ螟ァ縺励※
#	pathname縺継tn縺ォ荳€閾エ縺励◆繧画升繧翫▽縺カ縺吶€ゅ◎縺ョ蜈医�繝輔か繝ォ繝€繧りヲ九↑縺九▲縺溘%縺ィ縺ォ縺輔l繧九€�(prune)
#	-o or. 謠。繧翫▽縺カ縺輔l縺ェ縺九▲縺溽函縺肴ョ九j縺ォ蟇セ縺励※
#	-o type d 蟇セ雎。繝輔ぃ繧、繝ォ蜷阪′繝�ぅ繝ャ繧ッ繝医Μ縺九▽(-a) path蜷阪′/縺ァ邨ゅo縺」縺ヲ縺ェ縺�(!...蜷ヲ螳�)
#	縺ョ縺ェ繧峨�縲+}/\000繧貞�蜉帙€りソ斐j蛟、縺ッ縺薙%縺ァtrue縺ェ縺ョ縺ァ蠕後m縺ョ隧穂セ。縺ッ繧ケ繧ュ繝��縺輔l繧九€�
#	-o 荳翫′螟ア謨励€√▽縺セ繧翫ョ繧」繝ャ繧ッ繝医Μ縺ィ縺九§繧�↑縺��縺ェ繧峨�{}\000繧貞�蜉帙€�
#	-o縺ッelse縺ォ霑代>縲�
#	
#	遲我セ。繧ウ繝シ繝�
#	loop:
#	
#	mode=read_linkend_data();		(-L)
#	obj=search(dir);
#	
#	if (pathname == $ptn ){		ptn縺ッ繧キ繧ァ繝ォ繝代ち繝シ繝ウ. */縺ィ縺�??123*/縺ィ縺九€�
#		next
#	} else if (obj==dir && pathname != '*/') {
#		printf obj + '/' + '\000'
#		next
#	} else {
#		printf obj + '\000'
#		next
#	}
#	loopend
#