Só um exemplo do doc Harbour:
/* $DOC$
$AUTHOR$
2016 Pete D. <pete_westg@yahoo.gr>
$TEMPLATE$
Function
$NAME$
hb_AtI()
$CATEGORY$
API
$SUBCATEGORY$
Strings
$ONELINER$
Locates the position of a substring in a main string.
$SYNTAX$
hb_AtI( <cSearch>, <cString>, [<nStart>], [<nEnd>] ) --> nPos
$ARGUMENTS$
<cSearch> the sub-string to search for
<cString> The main string to search into, for <cSearch>
<nStart> Beginning search position into <cString>, default: 1
<nEnd> Ending search position, default: Length of <cString> (i.e. entire <cString>)
$RETURNS$
hb_AtI() returns the position (if any), into main string,
where first time the substring appears.
$DESCRIPTION$
This function has same functionality as hb_At() with the significant
difference that it's case Insensitive.
Optionally, with <nStart> can be defined the position into main string
from where the search of <cSearch> must begin and with <nEnd> the position
where it must stop. If neither of them is defined, <nStart> is 1st position
and <nEnd> the ending of <cString>.
$EXAMPLES$
? hb_At( "AS", "as simple as possible", 5 ) // --> 0
? hb_AtI( "AS", "as simple as possible", 5 ) // --> 11
$STATUS$
R
$COMPLIANCE$
H
$PLATFORMS$
All
$FILES$
Library is core
$SEEALSO$
hb_At()
$END$
*/
Aqui o teste básico que fiz pra converter, pegando alguns blocos, mas foi só pra um item.
#include "directry.ch"
PROCEDURE Main
LOCAL aDocList, cJSON, aTxtList, cTxt, aFile
SetMode(25,80)
CLS
Inkey(0)
aDocList := Directory( "*.txt" )
cJSON := "[" + hb_LF()
FOR EACH aFile IN aDocList
aTxtList := hb_RegExSplit( "$END$", MemoRead( aFile[ F_NAME ] ) )
FOR EACH cTxt IN aTxtList
cJSON += "{" + hb_LF()
cJSON += [ "NAME: ] + FromTo( cTxt, "NAME", "SYNTAX" ) + [" ,] + hb_LF()
cJSON += [ "SYNTAX: ] + FromTo( cTxt, "SYNTAX", "RETURNS" ) + [", ] + hb_LF()
cJSON += [ "RETURN: ] + FromTo( cTxt, "RETURNS", "DESCRIPTION" ) + [", ] + hb_LF()
cJSON += [ "DESCRIPTION: ] + FromTo( cTxt, "DESCRIPTION", "END" ) + ["]
cJSON += [, ] + hb_LF()
NEXT
NEXT
cJSON := Left( cJSON, Len( cJSON ) - 2 )
cJSON += hb_LF() + "]" + hb_LF()
hb_MemoWrit( "hwgui.hbd", cJSON )
RETURN
FUNCTION hb_LF()
RETURN Chr(10)
FUNCTION FromTo( cTxt, cFrom, cTo )
LOCAL nPosi, nPosf
cTxt := StrTran( cTxt, hb_EOL(), hb_LF() )
nPosi := hb_At( "$" + cFrom + "$", cTxt ) + Len( cFrom ) + 3
nPosf := hb_At( "$" + cTo + "$", cTxt ) - 1
IF nPosf == 0
nPosf := Len( cTxt )
ENDIF
cTxt := Substr( cTxt, nPosi, nPosf - nPosi + 1 )
DO WHILE Left( cTxt, 1 ) == hb_LF()
cTxt := Substr( cTxt, 2 )
ENDDO
DO WHILE Right( cTxt, 1 ) == hb_LF()
cTxt := Left( cTxt, Len( cTxt ) - 1 )
ENDDO
cTxt := StrTran( cTxt, hb_LF(), "\n" )
RETURN AllTrim( cTxt )
basicamente a rotina pega o que tem entre $NAME$ e $SYNTAX$, entre $SYNTAX$ e $RETURN$, etc.
E cria o TXT como json, com a extensão hbd, pronto pra ser usado pelo hbmk2.
Foi um teste só pra um comando, pra ver se funcionava.
Falta ajustar "}" e "]" pra fechar conjuntos de muitos comandos, e até de um comando só.
Fiz o acerto manualmente no teste.