#!/bin/sh
# GPL_3+
cat << 'EEE' > /dev/null
/* Copyright (C) 2021 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

cat << 'EEE' > /dev/null
#SH_doc
cat << 'EEE'
title=AMN section=1
repnl=\040	//dfl is repnl =(noset). change nl to \s for latin-langages
@name amn
@_brief man maker
@_syno amn [-hHV137] [-D key=str] [file|stdin]
@tl;dr
	make man:

	@(code)--
	~$ amn <<- EEE
	@name hw - hello, world
	@synopsis hw [-hH] file...
	@description disp 'hello', '_world'
	EEE
	
	~$ amn <<- EEE |man /dev/stdin 
	title=xyz section=3
	@name hw - hello, world
	@_syno
	#include "hw.h"
	int hw(int ac, char** av);
	@_desc use c-func parser in @synopsis if section is '_2' or '3'
	EEE
	@()--

	read from '_stdin' if ag1 '_file' isnt exist
	@(code)
	~$ anm src.txt
	~$ anm <src.txt
	~$ cat src.txt | anm | man /dev/stdin
	~$ cat src.txt | anm -D title=abc 
	@()
@_opt
	@(list_o)
	-h, -H, -V:	print usage, version info
	-1, -3, -7:	output sample command
	-D key=str: overwrite default settings
	@()
	opt '-D' '_key' are the below. val '_str' \[\abfnrtv], \ooo, \xhh is converted.
	null-char \0 causes undefined results. 
	@(pre)@
	'  mk   ': tag marker. used for charesc too. dfl=@'@@@'
	'  hlop ': bold/underline highlight block open. dfl=\047 (single quote)
	'  hlcl ': close. dfl=\047
	'  ulstr': underline flag. dfl=@'_@'. @'_str@' makes underline, '_str'
	'  tagop': tag open. @@(pre) etc. dfl=@'(@'
	'  tagcl': close. dfl=@')@'
	'  lbdlm': works only in @(list), -a@: info..., etc. dfl=@':@'
	'  brstr': break marker. dfl=@'--@'. --(\n) works as <br>.
	'  repnl': replace nl. dfl=  (del). latin-type lang may need \s==\040
	'  zwsp ': insert zwsp to all chars if set 1. dfl=0 
	         man misses locale if read file from local.
	           ~$ man abc.1		#>> valil, locale=ja_JP etc
	           ~$ cp /usr/share/man/ja/man1/abc.1.gz ./
	           ~$ man ./abc.1.gz		#>> broken format locale=C ?
	         man preprocesser causes this problem. abc.1.gz is valid.
	         zwsp temporary improves broken format at editing/making doc.
	         dont use zwsp to release doc. (h|e|l|l|o ...redundant)
	         you can resolve this probrem using groff delective '.mso'.
	           ~$ (echo .mso ja.tmac; cat ./abc.1) | man -l -
	         `-l -` means ` read local + stdin(-)`. see 'man(1), groff(7)'
	@()
	--
	next keys change manpage setting
	@(pre)@
	'  title'   : manpage title. dfl=no_title
	'  section' : man section. dfl=1
	'  footer'  : dfl isnt set
	'  footer_l': dfl isnt set
	'  header'  : dfl isnt set
	@()
@_desc
	amn converts markup text to manpages. basic rule is close to html.
	@(pre)@
	  - tab, newline, emptylines are ignored
	  - spaces are merged to 1 char
	@()
	a typical example is the below:
	@(code)@
	---
	  title=hello section=1
	  header=GNU  repnl=\040
	  @name hw
	  @_brief hello, world
	  @_syno hw [-h|-H] file ...
	  @options option list is --
	    @(list)
	    -h: escape quote, colon.. @'help@' @: etc
	    '-v': version
	    @() 
	  @_see ls(1), 'pwd(1)' '_puts(3)'
	---
	@()--
	
	amn accepts the following syntax:
	@(list)--
	'_key=str': from BOF to 1st @XXX is defination block. --
		- grep only XX=YY str. ignore others --
		- dont quote. mk=@'@@@' is bad. title=a\101c is valid. --
		- '_str' is sapareted with sp/tab. use \040 if needs space \s. --
		- '_str' is converted with printf('_str'). --
		- option -D'_key=str' overwrites defination block settings.	--
	'_@XXX': header, '@name' etc. make uppercase. must be BOL.
		XXX is converted with printf('XXX'). @conforming\040to etc.
	@_XXX: same as @XXX, but some words are reserved to alias/macros. --
		'  @_syno '@: @SYNOPSIS		--
		'  @_opt  '@: @OPTIONS		--
		'  @_desc '@: @DESCRIPTION	--
		'  @_eg   '@: @EXSAMPLE		--
		'  @_ver  '@: @VERSION		--
		'  @_see  '@: @SEE_ALSO		--
		'  @_brief'@: add description to @NAME	--
	'@(pre)...@()': <pre>..</pre>. highlighting, charesc, @@(raw) works
	'@(code)..@()': similar to @(pre) but any syntax/tag doesnt work

	'@(list)..@()': list. splits label and info with colon @'@:@'.
		if use colon char in infostr, use '@@:' . nl, --(\n) cant use in label. --
		''eg) it@@'s a 'la'@'_bel': m'sg' @@: --(\n)@(raw).RS@()  ..valid''	--

	'@(list_o)..@()': list for command options. highlight label automatically --
		''eg) -n, --num[=n]: set num >>>'' '-n', '--num'[='_n'] set num

	'@(raw)...@()': pass rawstr to groff. no needs to set \n at the block end. --
		''eg) abc@(raw).SH new_section@()123''

	'@()(\n)': works as block end if exists in the EOL. if block isnt open or
		not EOL, ignored/skipped. --
		''eg) abc@()123 >>> abc123, do nothing''

	@'str@'		: bold 'str'. keep inner sp/tabs. use '@@@', @@@@' to write '@', @@'
	@'_str@'	: underline '_str'. 1 char @'_@' works as bold
	@'@'str@'@'	: single quote x2, no highlighting. you dont need esc quote. --
		''eg) '@' 'abc' esc @@' @@@@ works too'@''' >>'' 'abc' esc ' @@ works too''
	'@@@''	: single quote. you can also use groff esc '@(raw) \(aa @()'
	'@@@@'	: atmark. you can also use groff '@(raw) @ @()'
	'@@:'	: colon. maybe uses only for @(list) or @(list_o). '@(raw) : @()'
	'--(\n)': 2-hyphen + nl. <br>. --(\s)(\n) doesnt work. 'gnu_man' seems
		to merge blanklines at output, so you cant use multi-blankslines. --
	@()

	if @@(pre,code,list,list_o) end with @@(...)\n, deletes \n char. --
	if they end with @@(...)--\n, add a empty line before the block. --
	if @@(pre,code) block end with @@(...)@@\n, remove the leading tabs as
	shell heredoc '' '<<-' '' syntax. --
	if they end with @@(...)--@\n, add a empty lines and remove the leading tabs.	--
	if @@() end with @@()--\n or @@()--@@\n, add a empty line after block.	--
	if @@() end with @@()@@\n, work the same as @@()\n. (ignores end @@). --
	summary example is the below:

	@(code)--@
	aaa              aaa          |  aaa              aaa
	@(code)          \t   \s 000  |  @(code)@            000
	\t   \s 000  >>  \s \t   111  |          000  >>          111
	\s \t   111      zzz          |          111
	@()\n                         |  @()--            zzz
	zzz                           |  zzz
	- - - - - - - - - - - - - - - + - - - - - - - - - - - - - - -
	aaa              aaa          |  aaa              aaa
	@(code)--                     |  @(code)--@ 
	        000  >>          000  |          000  >>     000
	        111              111  |          111              111
	@()@             zzz          |  @()--@ 
	zzz                           |  zzz              zzz
	@()--@

	the @(list_o) label and @SYNOPSIS block are highlighted automatically.
	@@(list_o) label is assumed to be command options -a, --all[=str] etc. --
	@SYNOPSIS parser is changed by '-Dsection'='_num' setting
	@(list)
	section 1:	detect command format, "cmd [-a ag] file" etc. use --(\n)
		to split long command description@: --
		'    'eg) cmd [-a ag] --(\n)(\t) [-b] file
	section 2/3: detect C-func decreations "int myf(int num);" etc. use 
		simple (\n) to split long string. (allow --(\n) too)--
		this block works as @@(pre) block with C-func highlighting.
	@()--
	the parsers are heuristic but work for the most part.
	
@_eg
	@(code)--@
		--
		@name hw - hello, world
		@_desc disp --
		  @(raw)...@() 
		  'messages' ...
		
		--
		mk=#_@ brstr=???
		#_@name hw - hello, world
		#_@_desc disp ???
		  #_@(raw)...#_@() 
		  'messages' ...
	@()--@

@conforming_to	posix-sh, POSIX.1-2001+
@notes
	@(code)
if you needs to html converter, use mandoc.
 ~$ cat amn.1 | mandoc -Thtml > amn.1.html
 ~$ cat amn.1 | mandoc -Tpdf > amn.1.pdf

gnu_man has self html parser (man -H) but not so good 
 ~$ cat amn.1 |man -Hcat /dev/stdin > amn.1.html

if you needs plaintext, man or mandoc.
 ~$ mandoc -Tutf8 <amn.1 | sed -e "s/.`printf '\\b'`//g"> amn.1.txt
 ~$ amn -7|amn -Dzwsp=1 |
		man -Tutf8 /dev/stdin|sed -e "s/.`printf '\\b'`//g"> amn.7.txt
 (-Dzwsp=1 + man makes terminal 80x24 suitable text in multibyte locale)
	@()
@copyright
	Copyright (C) 2021 Momi-g --
	License GPLv3+ <https://gnu.org/licenses/gpl.html>.

@_see
	'man-pages(7)', 'groff_man(7)', 'groff(7)', 'mandoc(1)'	--
	https://wiki.archlinux.org/title/Man_page (strongly recommend)	--
	--
	...recommend to read man-pages(7)
#SH_docE
EEE
version_info(){
cat << 'EEE'
amn v1.0.3
Copyright (C) 2021 Momi-g
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
EEE
exit 0
}

usage(){
cat << 'EEE'
HowTo (amn - manpage maker)
opt: -hH(elp), -V(er), -D(ef), -137(sample output)
---
eg) ~$ amn -1	#>> copy & run output code 
   
    ~$ echo "
@name myapp - amn     'ignores' '_blanks'/nl same as html
@synopsis mycomm [-a|-b] [-d word] words
	" | amn | man /dev/stdin

 amn makes a manpage from plain text. syntax is:
    @str   : section header, .SH, <h2> etc. set to BOL
    'str'  : bold (and you can use as space holder, '  str')
    '_str' : underline
    ''str'': no highlight. ''it's good'' == it@'s good
    --(\n) : break, <br>. amn skips newline and tab
    @(...) : other format/setting tag

 @SYNOPSIS block is highlighted automatilcally.
 see detail: ~$ amn -H
EEE
exit 0
}
usage_H(){
 cat << 'E E'|sed -e'1d;$d'
/*--copyfrom amn.1.txt*/
AMN(1)                      General Commands Manual                     AMN(1)



NAME
       amn - man maker

SYNOPSIS
       amn [-hHV137] [-D key=str] [file|stdin]

TL;DR
       make man:

            ~$ amn <<- EEE
            @name hw - hello, world
            @synopsis hw [-hH] file...
            @description disp "hello", "_world"
            EEE

            ~$ amn <<- EEE |man /dev/stdin
            title=xyz section=3
            @name hw - hello, world
            @_syno
            #include "hw.h"
            int hw(int ac, char** av);
            @_desc use c-func parser in @synopsis if section is "_2" or "3"
            EEE

       read from stdin if ag1 file isnt exist
            ~$ anm src.txt
            ~$ anm <src.txt
            ~$ cat src.txt | anm | man /dev/stdin
            ~$ cat src.txt | anm -D title=abc


OPTIONS
       -h, -H, -V
              print usage, version info

       -1, -3, -7
              output sample command

       -D key=str
              overwrite default settings

       opt -D key are the below. val str \[\abfnrtv], \ooo, \xhh is converted.
       null-char \0 causes undefined results.
         mk   : tag marker. used for charesc too. dfl='@'
         hlop : bold/underline highlight block open. dfl=\047 (single quote)
         hlcl : close. dfl=\047
         ulstr: underline flag. dfl='_'. '_str' makes underline, str
         tagop: tag open. @(pre) etc. dfl='('
         tagcl: close. dfl=')'
         lbdlm: works only in @(list), -a: info..., etc. dfl=':'
         brstr: break marker. dfl='--'. --(\n) works as <br>.
         repnl: replace nl. dfl=  (del). latin-type lang may need \s==\040
         zwsp : insert zwsp to all chars if set 1. dfl=0
                man misses locale if read file from local.
                  ~$ man abc.1       #>> valil, locale=ja_JP etc
                  ~$ cp /usr/share/man/ja/man1/abc.1.gz ./
                  ~$ man ./abc.1.gz       #>> broken format locale=C ?
                man preprocesser causes this problem. abc.1.gz is valid.
                zwsp temporary improves broken format at editing/making doc.
                dont use zwsp to release doc. (h|e|l|l|o ...redundant)
                you can resolve this probrem using groff delective .mso.
                  ~$ (echo .mso ja.tmac; cat ./abc.1) | man -l -
                `-l -` means ` read local + stdin(-)`. see man(1), groff(7)

       next keys change manpage setting
         title   : manpage title. dfl=no_title
         section : man section. dfl=1
         footer  : dfl isnt set
         footer_l: dfl isnt set
         header  : dfl isnt set


DESCRIPTION
       amn converts markup text to manpages. basic rule is close to html.
         - tab, newline, emptylines are ignored
         - spaces are merged to 1 char
       a typical example is the below:
       ---
         title=hello section=1
         header=GNU  repnl=\040
         @name hw
         @_brief hello, world
         @_syno hw [-h|-H] file ...
         @options option list is --
           @(list)
           -h: escape quote, colon.. @"help@" @: etc
           "-v": version
           @()
         @_see ls(1), "pwd(1)" "_puts(3)"
       ---

       amn accepts the following syntax:


       key=str
              from BOF to 1st @XXX is defination block.
              - grep only XX=YY str. ignore others
              - dont quote. mk='@' is bad. title=a\101c is valid.
              - str is sapareted with sp/tab. use \040 if needs space \s.
              - str is converted with printf(str).
              - option -Dkey=str overwrites defination block settings.


       @XXX   header, @name etc. make uppercase. must be BOL. XXX is converted
              with printf(XXX). @conforming\040to etc.

       @_XXX  same as @XXX, but some words are reserved to alias/macros.
                @_syno : @SYNOPSIS
                @_opt  : @OPTIONS
                @_desc : @DESCRIPTION
                @_eg   : @EXSAMPLE
                @_ver  : @VERSION
                @_see  : @SEE_ALSO
                @_brief: add description to @NAME


       @(pre)...@()
              <pre>..</pre>. highlighting, charesc, @(raw) works

       @(code)..@()
              similar to @(pre) but any syntax/tag doesnt work

       @(list)..@()
              list. splits label and info with colon ':'. if use colon char in
              infostr, use @: . nl, --(\n) cant use in label.
              eg) it@"s a "la"'_bel": m"sg" @: --(\n)@(raw).RS@()  ..valid


       @(list_o)..@()
              list for command options. highlight label automatically
              eg) -n, --num[=n]: set num >>> -n, --num[=n] set num

       @(raw)...@()
              pass rawstr to groff. no needs to set \n at the block end.
              eg) abc@(raw).SH new_section@()123

       @()(\n)
              works as block end if exists in the EOL. if block isnt  open  or
              not EOL, ignored/skipped.
              eg) abc@()123 >>> abc123, do nothing

       'str'  bold str. keep inner sp/tabs. use @', @@ to write ', @

       '_str' underline str. 1 char '_' works as bold

       ''str''
              single quote x2, no highlighting. you dont need esc quote.
              eg) "' "abc" esc @" @@ works too"' >> "abc" esc " @ works too

       @'     single quote. you can also use groff esc @(raw) \(aa @()

       @@     atmark. you can also use groff @(raw) @ @()

       @:     colon. maybe uses only for @(list) or @(list_o). @(raw) : @()

       --(\n) 2-hyphen  +  nl.  <br>. --(\s)(\n) doesnt work. gnu_man seems to
              merge blanklines at output, so you cant use multi-blankslines.


       if @(pre,code,list,list_o) end with @(...)\n, deletes \n char.
       if they end with @(...)--\n, add a empty line before the block.
       if @(pre,code) block end with @(...)@\n, remove  the  leading  tabs  as
       shell heredoc  "<<-"  syntax.
       if  they end with @(...)--@\n, add a empty lines and remove the leading
       tabs.
       if @() end with @()--\n or @()--@\n, add a empty line after block.
       if @() end with @()@\n, work the same as @()\n. (ignores end @).
       summary example is the below:

       aaa              aaa          |  aaa              aaa
       @(code)          \t   \s 000  |  @(code)@            000
       \t   \s 000  >>  \s \t   111  |          000  >>          111
       \s \t   111      zzz          |          111
       @()\n                         |  @()--            zzz
       zzz                           |  zzz
       - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - -
       aaa              aaa          |  aaa              aaa
       @(code)--                     |  @(code)--@
               000  >>          000  |          000  >>     000
               111              111  |          111              111
       @()@             zzz          |  @()--@
       zzz                           |  zzz              zzz

       the @(list_o) label and @SYNOPSIS block are highlighted  automatically.
       @(list_o) label is assumed to be command options -a, --all[=str] etc.
       @SYNOPSIS parser is changed by -Dsection=num setting

       section 1
              detect  command  format,  "cmd  [-a ag] file" etc. use --(\n) to
              split long command description:
                  eg) cmd [-a ag] --(\n)(\t) [-b] file

       section 2/3
              detect C-func decreations "int myf(int num);" etc.  use   simple
              (\n) to split long string. (allow --(\n) too)
              this block works as @(pre) block with C-func highlighting.

       the parsers are heuristic but work for the most part.

EXSAMPLE
       --
       @name hw - hello, world
       @_desc disp --
         @(raw)...@()
         "messages" ...

       --
       mk=#_@ brstr=???
       #_@name hw - hello, world
       #_@_desc disp ???
         #_@(raw)...#_@()
         "messages" ...



CONFORMING_TO
       posix-sh, POSIX.1-2001+

NOTES
       if you needs to html converter, use mandoc.
        ~$ cat amn.1 | mandoc -Thtml > amn.1.html
        ~$ cat amn.1 | mandoc -Tpdf > amn.1.pdf

       gnu_man has self html parser (man -H) but not so good
        ~$ cat amn.1 |man -Hcat /dev/stdin > amn.1.html

       if you needs plaintext, man or mandoc.
        ~$ mandoc -Tutf8 <amn.1 | sed -e "s/.`printf "\\b"`//g"> amn.1.txt
        ~$ amn -7|amn -Dzwsp=1 |
                 man -Tutf8 /dev/stdin|sed -e "s/.`printf "\\b"`//g"> amn.7.txt
        (-Dzwsp=1 + man makes terminal 80x24 suitable text in multibyte locale)


COPYRIGHT
       Copyright (C) 2021 Momi-g
       License GPLv3+ <https://gnu.org/licenses/gpl.html>.

SEE_ALSO
       man-pages(7), groff_man(7), groff(7), mandoc(1)
       https://wiki.archlinux.org/title/Man_page (strongly recommend)

       ...recommend to read man-pages(7)



                                                                        AMN(1)
/*--copyend amn.1.txt*/
E E
exit 0
}

set -ue
# posix: 2.5.3 Shell Variables
#If the shell is not currently executing a script or function, the value of LINENO is unspecified. 
#--- from license: cc-by-sa 3.0 (code is changed from the orig)
# https://stackoverflow.com/questions/17804007	Q: dspjm  ->  A: devnull
PS4='${LINENO-noPsx+}: '
#--- end license:	cc-by-sa 3.0

d_input=""
amn_main(){
cmd=$(cat << 'END'   # 'END'.. not expand $foo etc. 
# opt dfl  type	( +add command you want to test input opt)	
	-h  0		bool	'usage'
	-H  0		bool	'usage_H'
	-1  0		bool	'usage_1'
	-3  0		bool	'usage_3'
	-7  0		bool	'usage_7'
	-V  0		bool	'version_info'
	-D  ""		str		'read_D "$opt_D"'
END
)
buf=`$exdir/ckopt "$cmd"`  #..or.. "$cmd"  (colon, quiet err mode as getopts )
eval "$buf"

if [ $# = 0 ];then
	set -- /dev/stdin
fi

cmd="awk $d_input "' -v exdir="$exdir" "$code"'
eval "$cmd"<$1
}
read_D(){
	k=${1%%=*}
	buf=" mk hlop hlcl tagop tagcl lbdlm brstr ulstr repnl title section footer footer_l header zwsp "
	if [ "${buf##* $k *}" != "" ];then
		printf "ERR: -Dtitle='abc' etc. allow keys:\n$buf\n" >/dev/stderr
		echo " ...bad key: $1">/dev/stderr
		exit 1
	fi
	v=${1#*=}
	set -- "$v"
	eval "$k="'"$1"'
	d_input="$d_input -v $k"'="$'"$k"'"'
}

code=$(cat<<'EEE'
BEGIN{
	gflg= -1
	idx=0
	eflg=0
	hname=0
	
	flname=exdir "/amn_cmn.ped"
	amn_cmn=""
	while( (getline buf<flname) > 0){ amn_cmn=amn_cmn "\n" buf }
	close(flname)
	sv=amn_cmn
	amn_cmn="$(cat<<'E E'\n" amn_cmn "\nE E\n)\n"

	flname=exdir "/amn_cmd.ped"
	amn_cmd=""
	while( (getline buf<flname) > 0){ amn_cmd=amn_cmd "\n" buf }
	close(flname)
	amn_cmd="$(cat<<'E E'\n" amn_cmd "\nE E\n)\n"

	flname=exdir "/amn_cfunc.ped"
	amn_cfunc=""
	while( (getline buf<flname) > 0){ amn_cfunc=amn_cfunc "\n" buf }
	close(flname)
	amn_cfunc="$(cat<<'E E'\n" amn_cfunc "\n" sv "\nE E\n)\n"
#print(amn_cfunc)>"/dev/stderr"
	split("", darr)
	darr["mk"]   = "@"		#cmn_mk
	darr["hlop"]= "\047"	#cmn_hlop
	darr["hlcl"]= "\047"	#cmn_hlcl
	darr["tagop"]= "("		#cmn_tagop
	darr["tagcl"]= ")"		#cmn_tagcl
	darr["lbdlm"]= ":"		#cmn_tagcl
	darr["brstr"]= "--"		#cmn_brstr
	darr["ulstr"]= "_"		#cmn_ulstr
	darr["repnl"]= ""		#cmn_repnl
	darr["zwsp"]= ""		#cmn_zwsp

	darr["title"]= "no_title"
	darr["section"]= 1

	if(mk!=""   ){ darr["mk"]   =mk   ; Darr["mk"]   =1 }	#cmn_mk
	if(hlop!=""){ darr["hlop"]=hlop; Darr["hlop"]=1 }	#cmn_hlop
	if(hlcl!=""){ darr["hlcl"]=hlcl; Darr["hlcl"]=1 }	#cmn_hlcl
	if(tagop!=""){ darr["tagop"]=tagop; Darr["tagop"]=1 }	#cmn_tagop
	if(tagcl!=""){ darr["tagcl"]=tagcl; Darr["tagcl"]=1 }	#cmn_tagcl
	if(lbdlm!=""){ darr["lbdlm"]=lbdlm; Darr["lbdlm"]=1 }	#cmn_tagcl
	if(brstr!=""){ darr["brstr"]=brstr; Darr["brstr"]=1 }	#cmn_brstr
	if(ulstr!=""){ darr["ulstr"]=ulstr; Darr["ulstr"]=1 }	#cmn_ulstr
	if(repnl!=""){ darr["repnl"]=repnl; Darr["repnl"]=1 }	#cmn_ulstr
	if(zwsp!=""){ darr["zwsp"]=zwsp; Darr["zwsp"]=1 }		#cmn_zwsp

	if(title!=""){    darr["title"]   = title   ; Darr["title"]   =1 }
	if(section!="" ){ darr["section"] =	section	; Darr["section"] =1 }
	if(footer !="" ){ darr["footer"]  =	footer	; Darr["footer"]  =1 }
	if(footer_l!=""){ darr["footer_l"]=	footer_l; Darr["footer_l"]=1 }
	if(header!=""  ){ darr["header"]  =	header	; Darr["header"]  =1 }
	#footer, footer_l, headerは基本無し
}

isSH() && gflg== -1 {
	gflg=0
	for(k in darr){
		darr[k]=o2s(darr[k]) 
		v=darr[k]
		gsub("'", "\\'", v)
		v="'" v "'"
		rg="\n[^\n]*#cmn_" k "\n"
		rep="\ncmn_" k "<- " v "\n"
		if(k=="repnl"){ rg="cmn_" k; rep=v }	#cmn_repnl
		if(k=="zwsp"){
			# add, insert \: to all char or not
			rg="cmn_" k
			rep=v
#print(rg "@" v (v!="'0'")) > "/dev/stderr"
			if(v=="''"||v=="'0'"){rep="''"}
			else{rep="'\134\134:'"}
#print(rg "@" rp) > "/dev/stderr"
			gsub(rg, rep, amn_cmn)
#print(amn_cmn) > "/dev/stderr"
			gsub(rg, rep, amn_cmd)
			gsub(rg, rep, amn_cfunc)
			continue
		}
		#cmn_zwsp, on-off
# print(k "@" v "@") > "/dev/stderr"
		sub(rg, rep, amn_cmn)
#print(amn_cmn) > "/dev/stderr"
		sub(rg, rep, amn_cmd)
		sub(rg, rep, amn_cfunc)
	}

# print(darr["brstr"] 123) >"/dev/stderr"
# print(amn_cmn) >"/dev/stderr"
# print(amn_cfunc) >"/dev/stderr"
# print(amn_cmd) >"/dev/stderr"
}

gflg== -1 {
	for(i=1;i<=NF;i++) {
		if( match($i,/[=]/)==0){continue}
		match($i,/^[^=]+/)
		k=substr($i, RSTART, RLENGTH)
		if( Darr[k] ){continue}
		if(0==match("title section footer footer_l header mk hlop hlcl tagop tagcl lbdlm brstr ulstr repnl zwsp", k) ) {
			printf( "ERR: key must be title,section,footer,footer_l,header,mk,hlop/cl,tagop/cl,lbdlm,brstr,ulstr,repnl,zwsp: %s\n", $0) > "/dev/stderr"
			eflg=1
			exit(1)
		}
		sub(/^[^=]+=/, "", $i)
		v=$i
		if(match(v, /[ \t\n\r]/) ){
			printf( "ERR: detect \\s\\t\\n\\r in define words: %s\n", $0) > "/dev/stderr"
			eflg=1
			exit(1)
		}
		darr[k]=v
#print(darr[k]) >"/dev/stderr"
#darr[k]=o2s(v) 	#完了時blkに移動
#print(i k v 123 darr[k]) >"/dev/stderr"
	}
	next
}

!hname{ sarr[gflg]=sarr[gflg] $0 "\n"; next }
hname {
		 if( hname=="_SYNO") { hname= "SYNOPSIS" }
	else if( hname=="_OPT" ) { hname= "OPTIONS"  }
	else if( hname=="_DESC") { hname= "DESCRIPTION" }
	else if( hname=="_EG"  ) { hname= "EXSAMPLE" }
	else if( hname=="_VER" ) { hname= "VERSION"  }
	else if( hname=="_SEE" ) { hname= "SEE_ALSO" }

	$1=""
	sub(/^[ \t]*/, "", $0)
	if(NF==0){ sarr[hname]=sarr[hname] darr["brstr"] "\n" }
	else { sarr[hname]=sarr[hname] darr["brstr"] "\n" $0 "\n" }
	idx++
	narr[idx]=hname
	gflg=hname
	next
}
END{
	if(eflg){ exit(eflg) }
	if( "_BRIEF" in sarr){
		sub(/\n$/, "", sarr["NAME"])
		buf = substr(sarr["_BRIEF"], length(darr["brstr"])+2)	#\n
		sarr["NAME"] = sarr["NAME"] " - " buf
	}
	printf(".TH %s %s %s %s %s\n", toupper(darr["title"]), darr["section"],
		darr["footer"], darr["footer_l"], darr["header"] )
	for(i=1;i in narr;i++){
		label=narr[i]
		if(label=="_BRIEF"){continue}
		str=sarr[label]
		output(label, str)
	}
}

function isSH(label	,str ,buf ,dmy, rc){
	buf= darr["mk"] darr["tagop"]
	hname= ((index($0, darr["mk"])==1) && (index($0, buf)!=1))
	if(! hname){ return 0 }

	dmy= substr($1,  length(darr["mk"])+1)
	buf= toupper(o2s(dmy))
	hname=buf
	if(label==""){ return hname=buf}
	if(buf== toupper(label) ){ return hname=buf }
	return hname=0
}

function output(key, str	,buf ,dmy){
#print(darr["section"] key) > "/dev/stderr"
	buf=""
	if(key=="SYNOPSIS" && darr["section"]==1){
		buf="a=" amn_cmd exdir "/ped -re \"$a\"|sed -e '1,2d'"
		printf(".SH SYNOPSIS\n")
		printf("%s\n", str) | buf
		close(buf)
#printf("\n")
		return 0
	}
	if(key=="SYNOPSIS" && (darr["section"]==2||darr["section"]==3) ){
		buf="a=" amn_cfunc exdir "/ped -re \"$a\"|sed -e '1,2d'"
#print(buf)>"/dev/stderr"
		printf(".SH SYNOPSIS\n")
		printf("%s\n", str) | buf
		close(buf)
#printf("\n")
		return 0
	}
# others
	buf="a=" amn_cmn exdir "/ped -re \"$a\"|sed -e '1,2d'"
	printf(".SH %s\n", key)
	printf("%s\n", str) | buf
	close(buf)
#printf("\n")
	return 0
}

function o2s(str	,buf){
	if(length(str)==0){return ""}
	gsub(/%/, "%%", str)
	cmd="printf -- \"$(cat<<'E E'\n" str "\nE E\n)\""
	cmd | getline buf
	close(cmd)
	return buf
}
EEE
)

usage_1(){
cat << 'EEE'
./amn <<- E | man /dev/stdin 
@name myapp - amn     'ignores' '_blanks'/nl same as html
@synopsis mycomm [-a|-b] [-d word] words...
E

#...copy & run upper code
EEE
exit 0
}

usage_3(){
cat << 'EEE'
./amn <<- E | man /dev/stdin
title=hellword section=3
@name hw - use C-func parser to @synopsis if section is '_2' or '3'
@_syno int hw(int ac, char** av); //write '_anymsg'
E

#...copy & run upper code
EEE
exit 0
}

usage_7(){
cat << 'EEE'
title=へろー section=7
repnl=	//nl削除デフォルトを使用
@name amn - マルチバイトlangなメモ
@_desc
	amnは
	@(pre)--@
		- javadocコメントのような簡潔な記述を
		- latin系以外の文字でも記載できて
		- roffという標準的なシステムで処理して
		- プログラマのdoc作成の'_労力を最小限'に
	@()--
	することが目的です。そのためにamnは
	@(pre)--@
		- 改行の空白変換を無効orオプション扱い
		- man表示が大きく崩れないようにcharactor毎にzwspを挿入できる
		  >>> (echo .mso ja.tmac;cat ./abc.1)|man -l - を見つけたので不要か
		- bold, listなどの必要最小限のシンタックスを導入
		- SYNOPSISの強調表示を自動化
	@()--
	の機能を担います。--
	--
	--以下、補足-- --
	manはバックエンドに(g)roffを使用する。roffはTeXと同じく書籍出版
	向けの組版プログラムのため、psとかpdfとか出力先に合わせて
	動作変更させたりミリメートル単位で位置を決めたり？出来る高機能
	なappだが 1970年代に作られたため基本はlatin系が主対象。
	そのため改行が自動で空白に変換される。 --
	http://manpages.ubuntu.com/manpages/bionic/ja/man7/roff.7.html --
	--
	roff言語は非常に難解。\"がコメントで\(rsがエスケープなど。
	扱うにはDTPオペレータ並の技量が必要で、古いため資料も限られる。
	manはマクロ事前定義によりある程度簡単に扱えるが、それでも太字指定など
	面倒な記述が多い。--
	amnは--
	'	' plain text >> amn内部パーサ >> manマクロ >> groff言語 --
	と変換して冗長な記述を不要にしている。既存のapp不採用の理由は
	@(list)--
	- html: 不要タグが多すぎ、記述が冗長。外部htmlパーサが必要
	- md: 暗黙、不可視なルールが多い。\s\s\nで<br>など。---前後で改行が必要
		などの行数が増えるシンタックスが多い。また外部md/htmlパーサが必要
	- tex: 外部パーサが必要。デカい重いオーバースペック。よく知らない。
	@()
	いずれも html/tex >> roff の非標準な外部パーサが必須であり、
	SYNOPSISの自動ハイライト機能もないので却下。--
	自動強調は非常に重要な機能です。doc書きは気力と時間を吸い取るので
	細かい指定が必要となると、もう書くのやーめた。となります。
	95%のdocは読まれず、4%は斜め読みで捨てられ、残り1%は少し読まれる。
	そのうちの0.1%は本当に重要なので誰かが分かりやすく書き直す。
	ゆえに整形やデザインに時間をかけるのはコスパが悪い。 --
	doc書きは限界を越えて短く、分かりやすく、コンセプトを明解に伝えることに
	コストをかけたい。そのためhtmlやinfoなどの文書ツールよりも、ポータブルで
	軽くて最もよく使うmanの作成を省力化するappが欲しかったのです。
@notes -
@_see -
EEE
exit 0
}

readlinkp()(
 rc=0
 s2o=$(cat<<-'EEE'
od -An -to1 -v|sed -e 's/\([0-7]\{1,\}\)/\\&/g'|tr -dc '[0-7\\]'|sed -e 's/\\000/\n/g'
EEE
 )
 out='printf "%s\\000" "$s"'"|$s2o"
 [ "$1" != "-f" ] || { out='printf "$s\n"'; shift; }
 [ "$1" != "--" ] || shift
 in='printf "%s\0" "$@"'
 [ $# != 0 ]||in="cat"
 
 while read -r a; do
 a=`printf "$a"@`; a="${a%?}";  a="${a%/}"
 [ "${a##/*}" = "" ]||a="`pwd`/$a"
 a=$(printf '%s@\n' "$a"|sed -e ':l;s@/\./@/@g;tl')
 a="${a%?}"

 # \nと/../.././abc は合法なのですり潰す
 s="";
 while :;do
  [ ${#a} != 0 ] || break
  [ "${a%/..}" = "$a" ] || { a="${a%/*}"; a="${a%/*}"; continue; }
  s="/${a##*/}$s"
  a="${a%/*}"
 done
 #	[ -e "$s" ] || { printf '//';eval "$out";rc=1; continue; }
 sv="$s"
 while :;do
  [ ${#s} != 0 ] || { s="$sv"; break; }
  [ -L "$s" ] || { s="${s%/*}";continue; }
 # detect link
  while :;do
  buf=`printf '%s: symbolic link to @' "$s"`	#@ ...+1
  ss=`file "$s"|cut -b ${#buf}-;printf @`	#file >> name +\n
  ss="${ss%??}"
  s="$ss/${sv#$s}"
  s=${s%/}
  sv="$s"
  ! [ -d "$s" ] || s="$s"/
  [ -L "$s" ] || break 2
  done
 done
 eval "$out"
 done <<- E
`eval "$in"|eval "$s2o"`
E
 return $rc
)
 # readlinkp: end

exdir=`readlinkp -f "$0"`
exdir=$(dirname "$exdir")
amn_main "$@"

# ./amn -H|./amn| mandoc -Tpdf > amn_1.pdf



cat<<'EEE'>/dev/null
 change log
 --
2021-08-27	Momi-g	<dmy@dmy.dmy>

	* amn(amn) : import brp format

	* amn(amn) : update readlinkp
	
	* amn(amn_awk) : fix 2021-08-21 concat cfunc+cmn bug

2021-08-21	Momi-g	<dmy@dmy.dmy>

	* amn(amn_*.ped) : change CHAR \047 \(cq, \. >> h"\N'34'" , \N'46'

	* amn(amn_*.ped) : change cmd parser, -opt, --opt-sub etc

	* amn(amn_main) : change cfunc file >> concat cfunc+cmn file

2021-08-20	Momi-g	<dmy@dmy.dmy>

	* amn(awk-o2s) : fix -Dkey=str % >> %% conv.
	
	* amn(amn_*.ped) : change CHAR \047 \(cq >> h'\:' _0

2021-08-17	Momi-g	<dmy@dmy.dmy>

	* amn(amn) : add zwsp switch. v1.0.3

2021-08-15	Momi-g	<dmy@dmy.dmy>

	* amn(XXX.ped) : update ped pkg. fix ped rule. v1.0.2
	
	* amn(cmn.ped) : add @(code,pre) in @(list) infomsg.

2021-08-10	Momi-g	<dmy@dmy.dmy>

	* amn(END()) : fix title output >> toupper(title)

2021-08-08	Momi-g	<dmy@dmy.dmy>

	* amn(typo) : fix typo _breaf >> _brief
	
	* amn_cfunc.ped : fix sec 3 SYNOPSIS \s, \t ignore >> left

	* amn_cfunc.cmn(cmn_blk_h): exclude @(raw) from block header group
	
2021-08-07	Momi-g	<dmy@dmy.dmy>

	* amn(all) release v1.0.0

EEE
