#!/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=@` (back 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 locale + stdin(-)`. see `man(1), groff(7)`
	@()
	--
	next keys change manpage settings
	@(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@`@`	: backquote x2, no highlighting. you dont need esc quote. --
		``eg) `@` `abc` esc @@` @@@@ works too`@``` >>`` `abc` esc ` @@ works too``
	`@@@``	: back quote. you can also use groff esc `@(raw) \(ga @()`
	`@@@@`	: 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-blanklines. --
	@()

	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, use 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>.

@_ver 2021-12-02 v1.1.1
@_see
	`man-pages(7)`, `groff_man(7)`, `groff(7)`, `mandoc(1)`	--
	https://wiki.archlinux.org/title/Man_page --
	--
	...recommend to read man-pages(7), arch_wiki
#SH_docE
EEE
version_info(){
cat << 'EEE'
amn v1.1.1
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=` (back 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 locale + stdin(-). see man(1), groff(7)

       next keys change manpage settings
         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``
              backquote x2, no highlighting. you dont need esc quote.
              eg) `` `abc` esc @` @@ works too`` >> `abc` esc ` @ works too

       @`     back quote. you can also use groff esc @(raw) \(ga @()

       @@     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-blanklines.


       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, use 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>.

VERSION
       2021-12-02 v1.1.1

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

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



                                                                        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"]= "`"		#cmn_hlop
	darr["hlcl"]= "`"		#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 "$@"	#SH_MAIN

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



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

	* amn(amn) : fix 64bit, build script, doc. v1.1.1

2021-09-23	Momi-g	<dmy@dmy.dmy>

	* amn(amn) : v1.1.0. change dfl highlight ' >> `

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
