home *** CD-ROM | disk | FTP | other *** search
/ PC Press 1997 July / Sezamfile97_1.iso / msdos / clipper / ft_doc.arj / FT_DOC.PRG < prev    next >
Text File  |  1992-03-13  |  30KB  |  1,208 lines

  1. /*
  2.  * File......: FT_DOC.PRG
  3.  * Author....: Leo Letendre
  4.  * CIS ID....: 73607,233
  5.  * Date......: $Date:  11 Feb 1992  20:26:00 $
  6.  * Revision..: $Revision: 1.0    $
  7.  * Log file..: $Logfile:     $
  8.  *
  9.  * This is an original work by Leo Letendre and is placed in the
  10.  * public domain.
  11.  *
  12.  * Modification history:
  13.  * ---------------------
  14.  *
  15.  *    V1.00 
  16.  *    1/19/92  Initial Version
  17.  *
  18.  *    V1.01
  19.  *    3/13/92  Fixed ascii output which had too many form feeds
  20. */
  21. #include "directry.ch"
  22. #include "fileio.ch"
  23. #include "inkey.ch"
  24.  
  25. #define INFILELINE   10
  26. #define MODULELINE   12
  27. #define ERRORLINE    20
  28. #define LONGLINE     78
  29. #define LONGONELINE  60
  30.  
  31. STATIC nReadHandle, nWriteHandle
  32. STATIC aDirList
  33. STATIC aDocInfo:={}
  34. STATIC aLinkInfo:={}
  35. STATIC aAuthorList:={}
  36.  
  37. *-
  38. /*  $DOC$
  39.  *  $FUNCNAME$
  40.  *     FT_DOC
  41.  *  $CATEGORY$
  42.  *     Documentation
  43.  *  $ONELINER$
  44.  *     Extracts documentation from source files
  45.  *  $SYNTAX$
  46.  *      FT_DOC [-a] <cLinkName> [<cAtFile>]
  47.  *  $ARGUMENTS$
  48.  *      [-a] This flag produces an ascii text of the documentation with
  49.  *          a form feed between each doc set. Note: must be first if given.
  50.  *      <cLinkname> The name of the Norton Guides Library linkfile.
  51.  *      <cAtFile> The file name of a list of files to process. If absent
  52.  *          then *.PRG, *.C, *.ASM, *.CH are processed.
  53.  *  $RETURNS$
  54.  *      NIL
  55.  *  $DESCRIPTION$
  56.  *      This routine extracts the documentation out of all of the .PRG,
  57.  *      .C and .ASM files in the current directory. It creates a series of
  58.  *      text files containing the documentation which can be used with a lnk
  59.  *      file to compile and link into the NG file.
  60.  *
  61.  *      The input consists of the link file for the Norton Guide linker,
  62.  *      NGML. This file consists of commands which identify menu items. This
  63.  *      program looks at the menu items and the input file for each menu item 
  64.  *      and builds that input file from sources which have the $CATAGORY$ of
  65.  *      the same name. A batch file called "ASSEMBL.BAT" is created which
  66.  *      when run will concatenate all of the files produced from the sources
  67.  *      into files to be compiled by NGC. After compiling NGML is called
  68.  *      with the link file to link the library. (This assumes that all input
  69.  *      files for the Norton Guide come from the source code or have already
  70.  *      been compiled.)
  71.  *
  72.  *      If cAtFile is included in the command line then it is the source
  73.  *      of file names for processing. Otherwise all .PRG, .C, .ASM, and .CH
  74.  *      files in the current directory are processed. A subdirectory is
  75.  *      created in the current directory called NGI. This will contain all
  76.  *      of the sources used to create the Norton Guide. The files are NOT
  77.  *      deleted so you can alter then if you want and then run the ASSEMBL
  78.  *      command. The form of the cAtFile is one file name per line.
  79.  *
  80.  *      The information which is extracted is all that is contained between
  81.  *      the $DOC$ and the $END$ in the forum toolkit header. It is assumed that
  82.  *      the order has not been changed from that given in the Toolkit. Some
  83.  *      variation may be tolerated but I have not tested all possibilities.
  84.  *      It is also safer to leave a blank line after an entry if you do not
  85.  *      have anything to put in rather than having two $XXXX$ lines come in
  86.  *      succession. Also the first occurrence of author is used as the author 
  87.  *      for all routines in the file. If none is found it is listed as unknown.
  88.  *
  89.  *      A log file is produced called FT_DOC.LOG. It contains a listing of
  90.  *      all routines processed and their respective catagories. A file called
  91.  *      AUTHOR.TXT is also produced which contains a list of all authors.
  92.  *      DOCERR.LOG is created which contains all errors encountered during the
  93.  *      processing. Errors include lines which are too long, catagories not
  94.  *      found and the like.
  95.  *
  96.  *      NOTE: don't try the program on this source since I haven't made it 
  97.  *      ignore the extra $DOC and $ENDs.
  98.  *  $EXAMPLES$
  99.  *      C:>FT_DOC nanfor.lnk
  100.  *  $SEEALSO$
  101.  *
  102.  *  $INCLUDE$
  103.  *
  104.  *  $END$
  105.  */
  106.  
  107. FUNCTION FT_DOC(cFlags,cLinkName,cAtFile)
  108.  
  109. * LOCAL variables: 
  110. LOCAL aExtensions:={"*.PRG","*.C","*.ASM","*.CH"}
  111. LOCAL i, nItem, cBatName
  112. LOCAL lAscii
  113. LOCAL nSec1
  114. *
  115. * Entry Point
  116. *
  117. nSec1=SECONDS()
  118. * Delete log file if present
  119.  
  120. IF FILE("DOCERR.LOG")
  121.     DELETE FILE "DOCERR.LOG"
  122. ENDIF
  123.  
  124. * See if flag is there
  125.  
  126. IF .NOT.EMPTY(cFlags)
  127.     IF UPPER(cFlags)=="-A".OR.UPPER(cFlags)=="/A"
  128.         lAscii=.T.
  129.     ELSE
  130.         lAscii=.F.
  131.         cAtFIle=cLinkName
  132.         cLinkName=cFlags
  133.     ENDIF
  134. ENDIF
  135.  
  136. * Get the linkfile name and get the info in it
  137.  
  138. IF cLinkName=NIL
  139.     ? "Syntax: MAKENG [-a] <linkname> [<ifile.]"
  140.     ? "        Where -a creates an ascii file instead of a Norton Guide"
  141.     ? "              linkname is the name of the Norton Guide Link file"
  142.     ? "              iFile is a file containing a list of files to process"
  143.      ? "                    otherwise *.PRG, *.C, *.ASM and *.CH are used"
  144.     RETURN NIL
  145. ENDIF
  146.  
  147. * check to see if input files are present
  148. IF .NOT.FILE(cLinkName)
  149.     ? "Link file Not Found:",cLinkName
  150.     RETURN NIL
  151. ENDIF
  152.  
  153. IF .NOT.EMPTY(cAtFIle).AND..NOT.FILE(cAtFile)
  154.     ? "Indirect file Not Found:",cAtFile
  155.     RETURN NIL
  156. ENDIF
  157.  
  158. CLEAR SCREEN
  159. SET CURSOR OFF
  160.  
  161. fill_Link_info(cLinkName)
  162.  
  163. * See if ngi subdirectory is present
  164.  
  165. IF EMPTY(DIRECTORY("NGI.*","D"))
  166.     FT_MKDIR("NGI")
  167. ENDIF
  168.  
  169. IF cAtFile=NIL  // use all files in directory
  170.  
  171. * Loop through each of the types of files
  172.  
  173.     FOR i=1 TO LEN(aExtensions)
  174.  
  175. * Get the list of
  176.         aDirList=DIRECTORY(aExtensions[i])
  177.  
  178. * If there are any files then process them
  179.  
  180.         IF LEN(aDirList)>0 
  181.  
  182.             IF lAscii
  183.                 ASCIIFiles()
  184.             ELSE
  185.                 ProcessFiles()
  186.             ENDIF
  187.         ENDIF
  188.     NEXT
  189. ELSE
  190. * an indirect file was given so read it and use it
  191.  
  192.     aDirList=ReadAtFile(cAtFile)
  193.  
  194. * If there are any files then process them
  195.  
  196.     IF LEN(aDirList)>0 
  197.  
  198.         IF lAscii
  199.             ASCIIFILES()
  200.         ELSE
  201.             ProcessFiles()
  202.         ENDIF
  203.     ENDIF
  204.  
  205. ENDIF
  206.  
  207. * Now build text files for norton compiler based upon link file
  208. * first sort based upon catagory and filename. Not Fast but easy.
  209.  
  210. @ INFILELINE,0 CLEAR TO INFILELINE,MAXCOL()
  211. @ MODULELINE,0 CLEAR TO MODULELINE,MAXCOL()
  212. @ INFILELINE,30 SAY "Sorting input files"
  213.  
  214. ASORT(aDocInfo,,,{|a,b| UPPER(a[1]+" "+a[2])<UPPER(b[1]+" "+b[2])})
  215.  
  216.  
  217. * Now actually build the info
  218.  
  219. @ INFILELINE,0 CLEAR TO INFILELINE,MAXCOL()
  220. @ INFILELINE,30 SAY "Assembling "+IIF(lAscii,"documentation","NG");
  221.     +" input files"
  222.  
  223. IF FILE("assembl.bat")
  224.     DELETE FILE "assembl.bat"
  225. ENDIF
  226. SET ALTERNATE TO "assembl.bat"
  227. SET ALTERNATE ON
  228. SET CONSOLE OFF
  229.  
  230. ? "@Echo OFF"
  231. ? "ECHO Assembling input files"
  232.  
  233. FOR i=1 TO LEN(aDocInfo)
  234.  
  235. * Find match
  236.  
  237.     nItem=ASCAN(aLinkInfo,{|a| UPPER(ALLTRIM(a[1]))==UPPER(ALLTRIM(aDocInfo[i,1]))})
  238.     IF nItem>0
  239.  
  240.         IF i=1.OR..NOT.(ALLTRIM(aDocInfo[i-1,1])==ALLTRIM(aDocInfo[i,1]))
  241. * Make the first copy
  242.             ? "COPY NGI\"+ALLTRIM(aDocInfo[i,4]),aLinkinfo[nItem,2]
  243.         ELSE
  244. * This may be slow but I don't have to worry about line length
  245.             ? "TYPE NGI\"+ALLTRIM(aDocInfo[i,4])+" >>"+aLinkinfo[nItem,2]
  246.         ENDIF
  247.         aLinkInfo[nItem,3]=.T.
  248.     ELSE
  249. * Write the error message
  250.         SET ALTERNATE TO
  251.         SET ALTERNATE OFF
  252.         SET CONSOLE ON
  253.         write_error("Catagory not found: "+aDocInfo[i,1],,,,aDocInfo[i,4])
  254.         @ ERRORLINE,0 CLEAR TO ERRORLINE,MAXCOL()
  255.         @ ERRORLINE,20 SAY "Catagory not found: "+aDocInfo[i,1]+" in "+aDocInfo[i,4]
  256.         SET ALTERNATE TO "assembl.bat" ADDITIVE
  257.         SET ALTERNATE ON
  258.         SET CONSOLE OFF
  259.     ENDIF
  260.  
  261. NEXT
  262.  
  263. * Delete old files
  264.  
  265. /*FOR i=1 TO LEN(aLinkInfo)
  266.  
  267.     IF FILE(aLinkInfo[i,2]).AND.aLinkInfo[i,3]
  268.         DELETE FILE (aLinkInfo[i,2])
  269.     ENDIF
  270. NEXT
  271. */
  272. * Now assemble the output
  273.  
  274. IF .NOT. lAscii
  275.  
  276.     ? "REM Compile the sources"
  277.     ? "Echo Compiling the sources"
  278.  
  279.     FOR i=1 TO LEN(aLinkInfo)
  280.         IF aLinkInfo[i,3]
  281.             ? "NGC ",aLinkInfo[i,2]
  282.         ENDIF
  283.     NEXT
  284.  
  285.     ? "REM  Link the files"
  286.     ? "Echo Linking library"
  287.     ? "NGML",cLinkName
  288.     ? " "
  289.  
  290. * Send out list of files
  291.  
  292.     @ INFILELINE,0 CLEAR TO INFILELINE,MAXCOL()
  293.     @ INFILELINE,30 SAY "Writing summary file"
  294.  
  295. ENDIF
  296.  
  297. SET ALTERNATE TO "FT_DOC.LOG"
  298. SET ALTERNATE ON
  299. SET CONSOLE OFF
  300. FOR i=1 TO LEN(aDocInfo)
  301.     ? PAD(aDocInfo[i,1],15),PAD(aDocInfo[i,2],15),PAD(aDocInfo[i,4],15)
  302. NEXT
  303.  
  304. * Send out list of authors
  305.  
  306. @ INFILELINE,0 CLEAR TO INFILELINE,MAXCOL()
  307. @ INFILELINE,30 SAY "Writing Author file"
  308.  
  309. * sort the list
  310.  
  311. ASORT(aAuthorList,,,{|a,b| UPPER(a)<UPPER(b)})
  312.  
  313. * Now write it out
  314.  
  315. SET ALTERNATE TO "author.txt"
  316. SET ALTERNATE ON
  317. SET CONSOLE OFF
  318.  
  319. ? aAuthorList[1]
  320.  
  321. FOR i=2 TO LEN(aAuthorList)
  322.  
  323.     IF aAuthorList[i]<>aAuthorList[i-1] 
  324.         ? aAuthorList[i]
  325.     ENDIF
  326.  
  327. NEXT
  328.  
  329. SET CONSOLE ON
  330. SET ALTERNATE OFF
  331. SET ALTERNATE TO
  332.  
  333. @MAXROW()-1,0 SAY "Total Time = "+STR(SECONDS()-nSec1)
  334. @MAXROW(),0 SAY "Execute ASSEMBL.BAT to compile and link Guides"
  335.  
  336. * Return to caller
  337.  
  338. RETURN NIL
  339.  
  340. * End of MAIN()
  341.  
  342. *+
  343. STATIC FUNCTION ProcessFiles
  344. *
  345. * This routine and all accompaning database structures are 
  346. * Copyright (C) 1992 Leo J. Letendre. 
  347. *
  348. * Purpose: Process each of the files in the directory
  349. *
  350. * Modification History:
  351. *        Version    Date      Who       Notes
  352. *         V1.00     1/19/92   LJL       Initial Version
  353. *
  354. * Calling parameters: None
  355. *
  356. * Notes: None
  357. *-
  358. * LOCAL variables: 
  359.  
  360. #define D_NORMAL  1
  361. #define D_ARG     2
  362. #define D_SYNTAX  3
  363. #define D_IGNORE  4
  364. #define D_SEEALSO 5
  365. #define D_INCLUDE 6
  366.  
  367. LOCAL i, j, nFiles:=LEN(aDirList)
  368. LOCAL nCommentLen
  369. LOCAL lEof, lDoc, lDone
  370. LOCAL cBuffer
  371. LOCAL nEnd, nCount
  372. LOCAL CRLF:=CHR(13) + CHR(10)
  373. LOCAL cBar:="──────────────────────────────────────────────────────────────────────────────"+CRLF
  374. LOCAL nMode
  375. LOCAL cAuthor
  376. LOCAL cFuncName
  377. LOCAL cOneLine
  378. LOCAL cCatagory
  379. LOCAL cFileName
  380. LOCAL nLineCnt
  381. LOCAL cSeeAlso
  382. LOCAL cTemp, cChar
  383.  
  384. *
  385. * Entry Point
  386. *
  387. * Put up information labels
  388. @ INFILELINE, 20 SAY "Extracting: "
  389. @ MODULELINE, 20 SAY "Documenting: "
  390. * loop through all of the files
  391.  
  392. FOR i=1 TO nFiles
  393.  
  394. * Open file for input
  395.  
  396.     nCommentLen:=IIF(AT("*.ASM",UPPER(aDirList[i,F_NAME]))>0,2,3)
  397.     nReadHandle=FT_FUSE(aDirList[i,F_NAME])
  398.     @ INFILELINE,33 CLEAR TO INFILELINE, MAXCOL()
  399.     @ INFILELINE,33 SAY PAD(aDirList[i,F_NAME],12)+" Line:"
  400.     @ MODULELINE,33 CLEAR TO MODULELINE, MAXCOL()
  401.  
  402.     nLineCnt=0
  403.  
  404.     IF nReadHandle<0
  405.         write_error("Can't open file: (Dos Error "+STR(FERROR())+")",,,,aDirList[i,F_NAME])
  406.         @ ERRORLINE,0 CLEAR TO ERRORLINE,MAXCOL()
  407.         @ ERRORLINE,20 SAY "Can't open file: (Dos Error "+STR(FERROR())+") File="+aDirList[i,F_NAME]
  408.         LOOP
  409.     ENDIF
  410.     lEof=.F.
  411.     lDoc=.F.
  412. * First find the author
  413.  
  414.     cAuthor=""
  415.     lDone=.F.
  416.     DO WHILE .NOT.lDone
  417. * Author
  418.  
  419.         cBuffer=ReadLN(@lEof)
  420.         nLineCnt++
  421.         IF nLineCnt%10=0
  422.             @ INFILELINE,52 SAY STR(nLineCnt,5,0)
  423.         ENDIF
  424.         IF AT("Author....",cBuffer)>0
  425.             lDone=.T.
  426.             cAuthor=ALLTRIM(SUBSTR(cBuffer,AT(".:",cBuffer)+2))
  427.             AADD(aAuthorList,cAuthor)
  428.         ENDIF
  429.         lDone=lEof.OR.lDone
  430.         IF lEof
  431.             write_error("Author not found",,,,aDirList[i,F_NAME])
  432.             cAuthor="Unknown"
  433.             FT_FGOTOP()
  434.             nLineCnt=0
  435.             lEof=.F.
  436.         ENDIF
  437.     ENDDO
  438.  
  439. * loop to go through file
  440.  
  441.     DO WHILE .NOT.lEof
  442.  
  443. * Read a line
  444.  
  445.         cBuffer=TRIM(SUBSTR(ReadLN(@lEof),nCommentLen))
  446.         nLineCnt++
  447.         IF nLineCnt%10=0
  448.             @ INFILELINE,52 SAY STR(nLineCnt,5,0)
  449.         ENDIF
  450. * check to see if we are in doc mode or getting out of doc mode
  451.  
  452.         IF AT("$DOC$",cBuffer)>0
  453.             IF lDoc
  454.                 write_error("$DOC$ encountered during extraction of Doc";
  455.                     +" at line"+STR(nLinecnt,5,0),,,,aDirList[i,F_NAME])
  456.             ENDIF
  457.             lDoc=.T.
  458.             cBuffer=TRIM(SUBSTR(ReadLN(@lEof),;
  459.                     nCommentLen))
  460.             nLineCnt++
  461.             cCatagory:=cFuncName:=cSeeAlso:=""
  462.             nMode=D_IGNORE
  463.         ELSEIF AT("$END$",cBuffer)>0
  464.             IF .NOT.lDoc
  465.                 write_error("$END$ encountered outside of Doc area at line";
  466.                     +STR(nLinecnt,5,0),,,,aDirList[i,F_NAME])
  467.             ELSE
  468. * Add a new entry to our list of files
  469.  
  470.                 IF EMPTY(cCatagory)
  471.                     write_error("Blank Catagory",,,,aDirList[i,F_NAME])
  472.                     cCatagory="Unknown"
  473.                 ENDIF
  474.                 IF EMPTY(cFuncName)
  475.                     write_error("Blank Function Name",,,,aDirList[i,F_NAME])
  476.                     cFuncName="Unknown"
  477.                 ENDIF
  478.                 AADD(aDocInfo,{cCatagory,cFuncName,cOneLine,cFileName})
  479. * Now close down this little piece
  480.                 lDoc=.F.
  481.                 FWRITE(nWriteHandle,CRLF)
  482.                 FWRITE(nWriteHandle," ^bSource:^b "+aDirList[i,F_NAME];
  483.                         +CRLF+CRLF)
  484.                 FWRITE(nWriteHandle," ^bAuthor:^b "+cAuthor+CRLF)
  485.                 IF .NOT.EMPTY(cSeeAlso)
  486.                     FWRITE(nWriteHandle,"!seealso:"+cSeeAlso+CRLF)
  487.                 ENDIF
  488.                 FCLOSE(nWriteHandle)
  489.                 nMode=D_IGNORE
  490.             ENDIF
  491.  
  492.             @ MODULELINE, 33 CLEAR TO MODULELINE, MAXCOL()
  493.         ENDIF
  494.  
  495. * Act on the input
  496.         IF lDoc
  497. * 1) function name
  498.  
  499.             IF AT("$FUNCNAME$",cBuffer)>0
  500.                 cBuffer=ReadLN(@lEof)
  501.                 nLineCnt++
  502. * Save the function name
  503.                 cFuncName=UPPER(ALLTRIM(SUBSTR(cBuffer,nCommentLen)))
  504.                 @ MODULELINE, 33 CLEAR TO MODULELINE, MAXCOL()
  505.                 @ MODULELINE, 33 SAY cFuncName
  506.  
  507.                 nMode=D_NORMAL
  508.  
  509. * Open a new file
  510.                 IF AT("FT_",cFuncName)>0
  511.                     cTemp=SUBSTR(cFuncName,4)
  512.                 ELSE
  513.                     cTemp=cFuncName
  514.                 ENDIF
  515.  
  516.                 IF (nEnd:=AT("(",cTemp))>0
  517.                     cTemp=LEFT(cTemp,nEnd-1)
  518.                 ENDIF
  519.                 cFileName=""
  520.  
  521. * Strip off any other non-alphabetic/numeric characters
  522.                 FOR j=1 TO LEN(cTemp)
  523.                     cChar=SUBSTR(cTemp,j,1)
  524.                     IF (cChar>="0".AND.cChar<="9").OR.;
  525.                         (cChar>="A".AND.cChar<="Z").OR.cChar="_"
  526.                         cFileName+=cChar
  527.                     ENDIF
  528.                 NEXT
  529.  
  530. * See if file name is present already. If so then modify
  531.  
  532.                 cFileName=LEFT(cFileName,8)
  533.                 nEnd=1
  534.                 nCount=0
  535.                 DO WHILE nEnd>0
  536.                     nEnd=ASCAN(aDocInfo,{|a| a[4]==cFileName+".NGI"})
  537.                     IF nEnd>0
  538.  
  539. * This will break if there are more than 10 files with the same first
  540. * seven characters. We take our chances.
  541.  
  542.                         IF LEN(cFileName)=8
  543.                             cFileName=STUFF(cFileName,8,1,STR(nCount,1,0))
  544.                         ELSE
  545.                             cFileName+=STR(nCount,1,0)
  546.                         ENDIF
  547.                         nCount++
  548.                     ENDIF
  549.                 ENDDO
  550. * Add on the extension
  551.  
  552.                 cFileName=LEFT(cFileName,8)+".NGI"
  553.  
  554.                 nWriteHandle=FCREATE("NGI\"+cFileName)
  555.                 IF nWriteHandle<1
  556.                     ? "Error creating",cFileName,".ngi"
  557.                     write_error("Error creating",,,,cFileName+".ngi")
  558.                 ENDIF
  559. * 2) Category
  560.             ELSEIF AT("$CATEGORY$",cBuffer)>0
  561.                 cBuffer=ReadLN(@lEof)
  562.                 nLineCnt++
  563. * get the catagory
  564.                 cCatagory=ALLTRIM(SUBSTR(cBuffer,nCommentLen))
  565.  
  566. * 3) One line description
  567.  
  568.             ELSEIF AT("$ONELINER$",cBuffer)>0
  569.                 cBuffer=ReadLN(@lEof)
  570.                 nLineCnt++
  571.                 cOneLine=ALLTRIM(SUBSTR(cBuffer,nCommentLen))
  572.                 IF LEN(cOneLine)>LONGONELINE
  573.                     write_error("OneLine",cOneLine,nLineCnt,LONGONELINE,;
  574.                         aDirList[i,F_NAME])
  575.                 ENDIF
  576.  
  577. * Now start writing out what we know
  578.                 FWRITE(nWriteHandle,"!short: "+PAD(cFuncName,17)+cOneLine+CRLF)
  579.                 FWRITE(nWriteHandle," ^b"+cFuncName+CRLF)
  580.                 FWRITE(nWriteHandle," "+cOneLine+CRLF)
  581.                 FWRITE(nWriteHandle,cBar)
  582. * 4) all other stuff
  583.  
  584.             ELSE
  585.  
  586.                 IF AT("$SYNTAX$",cBuffer)>0
  587.  
  588.                     FWRITE(nWriteHandle," ^bSyntax"+CRLF)
  589.                     nMode=D_SYNTAX
  590.  
  591.                 ELSEIF AT("$ARGUMENTS$",cBuffer)>0
  592.  
  593.                     FWRITE(nWriteHandle," ^bArguments"+CRLF)
  594.                     nMode=D_ARG
  595.  
  596.                 ELSEIF AT("$RETURNS$",cBuffer)>0
  597.  
  598.                     FWRITE(nWriteHandle," ^bReturns"+CRLF)
  599.                     nMode=D_NORMAL
  600.  
  601.                 ELSEIF AT("$DESCRIPTION$",cBuffer)>0
  602.  
  603.                     FWRITE(nWriteHandle," ^bDescription"+CRLF)
  604.                     nMode=D_NORMAL
  605.  
  606.                 ELSEIF AT("$EXAMPLES$",cBuffer)>0
  607.  
  608.                     FWRITE(nWriteHandle," ^bExamples"+CRLF)
  609.                     nMode=D_NORMAL
  610.  
  611.                 ELSEIF AT("$SEEALSO$",cBuffer)>0
  612.                     nMode=D_SEEALSO
  613.                 ELSEIF AT("$INCLUDE$",cBuffer)>0
  614.                     nMode=D_INCLUDE
  615.  
  616. * All other input is trimmed of comments and sent out
  617.  
  618.                 ELSE
  619.                     IF nMode=D_SYNTAX
  620.                         IF LEN(cBuffer)>LONGLINE
  621.                             write_error("Syntax",cBuffer,nLineCnt,;
  622.                                     LONGLINE,aDirList[i,F_NAME])
  623.                         ENDIF
  624.                         FWRITE(nWriteHandle,"^a1f "+cBuffer+CRLF)
  625.                     ELSEIF nMode=D_ARG
  626.                         IF LEN(cBuffer)>LONGLINE
  627.                             write_error("Arguments",cBuffer,nLineCnt,;
  628.                                     LONGLINE,aDirList[i,F_NAME])
  629.                         ENDIF
  630.                         cBuffer=STRTRAN(cBuffer,"<","^b<",1)
  631.                         cBuffer=STRTRAN(cBuffer,">",">^b",1)
  632.                         FWRITE(nWriteHandle,cBuffer+CRLF)
  633.                     ELSEIF nMode=D_NORMAL
  634.                         IF LEN(cBuffer)>LONGLINE
  635.                             write_error("General",cBuffer,nLineCnt,;
  636.                                     LONGLINE,aDirList[i,F_NAME])
  637.                         ENDIF
  638.                         FWRITE(nWriteHandle,cBuffer+CRLF)
  639.                     ELSEIF nMode=D_SEEALSO
  640.                         IF .NOT.EMPTY(cBuffer)
  641.                             cSeeAlso=cBuffer
  642.                         ENDIF
  643.                     ELSEIF nMode=D_INCLUDE
  644. * read next line
  645.                         IF .NOT.EMPTY(cBuffer)
  646.                             FWRITE(nWriteHandle," ^bHeader File:^b ";
  647.                                 +cBuffer+CRLF+CRLF)
  648.                         ENDIF
  649.                     ENDIF
  650.                 ENDIF
  651.             ENDIF
  652.         ENDIF
  653.     ENDDO
  654. * Close down the input file
  655.  
  656.     FT_FUSE()
  657. NEXT
  658.  
  659.  
  660. RETURN NIL
  661.  
  662. * End of file process files
  663.  
  664. *+
  665. FUNCTION fill_link_info(cLinkName)
  666. *
  667. * This routine and all accompaning database structures are 
  668. * Copyright (C) 1992 Leo J. Letendre. 
  669. *
  670. * Purpose: read the link information to learn how to assemble database files
  671. *
  672. * Modification History:
  673. *        Version    Date      Who       Notes
  674. *         V1.00     1/22/92   LJL       Initial Version
  675. *
  676. * Calling parameters: cLinkName - The name of the link file
  677. *
  678. * Notes: looks for the !menu command and then reads the lines after it to
  679. *        get the catagories and filenames associated with each.
  680. *-
  681. * LOCAL variables: 
  682. LOCAL cBuffer, lEof, cSpace
  683. LOCAL cCatagory, cFile
  684. LOCAL lMenuMode:=.F.
  685. *
  686. * Entry Point
  687. *
  688. nReadHandle=FT_FUSE(cLinkName)
  689. lEof=.F.
  690.  
  691. DO WHILE .NOT. lEof
  692.  
  693. * Read a line
  694.     cBuffer=UPPER(ReadLN(@lEof))
  695.  
  696. * Does it have a !menu?
  697.  
  698.     IF AT("!MENU",cBuffer)>0
  699.         lMenuMode=.T.
  700.     ELSEIF LEFT(cBuffer,1)="!"
  701.         lMenuMode=.F.
  702.     ENDIF
  703.  
  704. * If we are in menu mode and the line has information on it then parse it
  705.  
  706.     cBuffer=ALLTRIM(cBuffer)
  707.  
  708.     IF .NOT.EMPTY(cBuffer)
  709.         cSpace=AT("  ",cBuffer)
  710.         cCatagory=UPPER(RTRIM(LEFT(cBuffer,cSpace-1)))
  711.         cFile=UPPER(LTRIM(SUBSTR(cBuffer,cSpace)))
  712.         cFile=STRTRAN(cFile,".NGO",".TXT")
  713.         AADD(aLinkInfo,{cCatagory,cFile,.F.})
  714.     ENDIF
  715.  
  716. ENDDO
  717.  
  718. * Close the file
  719.  
  720. FT_FUSE()
  721. * Return to caller
  722.  
  723. RETURN NIL
  724.  
  725. * End of fill_link_info
  726.  
  727. *+
  728. STATIC FUNCTION ReadAtFile(cAtFile)
  729. *
  730. * This routine and all accompaning database structures are 
  731. * Copyright (C) 1992 Leo J. Letendre. 
  732. *
  733. * Purpose: read in the users list of files to act on
  734. *
  735. * Modification History:
  736. *        Version    Date      Who       Notes
  737. *         V1.00     1/1/92   LJL       Initial Version
  738. *
  739. * Calling parameters: cAtFile - The name of the file containing a list of
  740. *                              files to be processed
  741. *
  742. * Returns: an array containing information that looks like it came
  743. *          from DIRECTORY() but only has the name present.
  744. *
  745. * Notes: 
  746. *-
  747. * LOCAL variables: 
  748. LOCAL aDirList:={}
  749. LOCAL cBuffer, lEof, nCount:=0
  750.  
  751. *
  752. * Entry Point
  753. *
  754. IF FT_FUSE(cAtFile)<>NIL
  755.  
  756. * Read each line
  757.     lEof=.F.
  758.     DO WHILE .NOT. lEof
  759.  
  760.         cBuffer=ALLTRIM(ReadLN(@lEof))
  761.         IF .NOT. EMPTY(cBuffer)
  762.             AADD(aDirList,ARRAY(F_LEN))
  763.             nCount++
  764.             aDirList[nCount,F_NAME]=UPPER(cBuffer)
  765.         ENDIF
  766.     ENDDO
  767. ENDIF
  768.  
  769. FT_FUSE()            
  770.  
  771. RETURN aDirList
  772.  
  773. * End of ReadAtFile
  774.  
  775.  
  776. STATIC FUNCTION write_error(cDesc, cBadLine, nLineCnt, nMax, cFile)
  777.  
  778. * This routine will send error messages to the error log - MAKENG.LOG
  779. *
  780. * Calling parameters: cDesc - Description of info being written
  781. *                     cBadLine - The offending line - IF NIL then just 
  782. *                                output cDesc and filename
  783. *                     nLineCnt - The line number of the bad line
  784. *                     nMax - The maximum length of the bad line
  785. *                     cFile - The file currently being processed
  786. *
  787. * Returns: NIL
  788. *
  789. * Entry point
  790. *
  791. * Point output to the log file
  792. SET ALTERNATE TO "DOCERR.LOG" ADDITIVE
  793. SET CONSOLE OFF
  794. SET ALTERNATE ON
  795.  
  796. * Send out the output
  797. IF cBadLine=NIL
  798.     ? cDesc,"in file",cFile
  799.     ? " "
  800. ELSE
  801.     ? "Line too long in file",cFile,"at line",ALLTRIM(STR(nLineCnt,10,0))
  802.     ? "Reading",cDesc,"information when line greater than",STR(nMax,2,0),"encountered:"
  803.     ? cBadLine
  804.     ? " "
  805. ENDIF
  806.  
  807. * Turn off the log file and return
  808.  
  809. SET ALTERNATE OFF
  810. SET CONSOLE ON
  811. SET ALTERNATE TO
  812.  
  813. RETURN NIL
  814.  
  815. * End of Write_Error
  816.  
  817. /***
  818. *  ReadLn( lEof ) --> cBuffer
  819. *
  820. * Read a line from the currently open file
  821. *
  822. * Parameters: lEof - Passed by reference - Logical indicating end of file
  823. *
  824. * Returns: The next line in the file without delimiters
  825. *
  826. */
  827. FUNCTION ReadLN( leof )
  828.  
  829.    LOCAL cBuffer := ""
  830.  
  831.     cBuffer=FT_FREADLN()
  832.     FT_FSKIP(1)
  833.     lEof=FT_FEOF()
  834.  
  835.    RETURN cBuffer
  836. * End of ReadLN
  837.  
  838. *+
  839. STATIC FUNCTION ASCIIFiles
  840. *
  841. * This routine and all accompaning database structures are 
  842. * Copyright (C) 1992 Leo J. Letendre. 
  843. *
  844. * Purpose: Process each of the files in the directory making an ascii file
  845. *
  846. * Modification History:
  847. *        Version    Date      Who       Notes
  848. *         V1.00     1/19/92   LJL       Initial Version
  849. *
  850. * Calling parameters: None
  851. *
  852. * Notes: None
  853. *-
  854. * LOCAL variables: 
  855.  
  856. LOCAL i, j, nFiles:=LEN(aDirList)
  857. LOCAL nCommentLen
  858. LOCAL lEof, lDoc, lDone
  859. LOCAL cBuffer
  860. LOCAL nEnd, nCount
  861. LOCAL CRLF:=CHR(13) + CHR(10)
  862. LOCAL cBar:="──────────────────────────────────────────────────────────────────────────────"+CRLF
  863. LOCAL nMode
  864. LOCAL cAuthor
  865. LOCAL cFuncName
  866. LOCAL cOneLine
  867. LOCAL cCatagory
  868. LOCAL cFileName
  869. LOCAL nLineCnt
  870. LOCAL cSeeAlso
  871. LOCAL cTemp, cChar
  872. LOCAL nDocCnt
  873.  
  874. *
  875. * Entry Point
  876. *
  877. * Put up information labels
  878. @ INFILELINE, 20 SAY "Extracting: "
  879. @ MODULELINE, 20 SAY "Documenting: "
  880. * loop through all of the files
  881.  
  882. FOR i=1 TO nFiles
  883.  
  884. * Open file for input
  885.  
  886.     nCommentLen:=IIF(AT("*.ASM",UPPER(aDirList[i,F_NAME]))>0,2,3)
  887.     nReadHandle=FT_FUSE(aDirList[i,F_NAME])
  888.     @ INFILELINE,33 CLEAR TO INFILELINE, MAXCOL()
  889.     @ INFILELINE,33 SAY PAD(aDirList[i,F_NAME],12)+" Line:"
  890.     @ MODULELINE,33 CLEAR TO MODULELINE, MAXCOL()
  891.  
  892.     nLineCnt=0
  893.  
  894.     IF nReadHandle<0
  895.         write_error("Can't open file: (Dos Error "+STR(FERROR())+")",,,,aDirList[i,F_NAME])
  896.         @ ERRORLINE,0 CLEAR TO ERRORLINE,MAXCOL()
  897.         @ ERRORLINE,20 SAY "Can't open file: (Dos Error "+STR(FERROR())+") File="+aDirList[i,F_NAME]
  898.         LOOP
  899.     ENDIF
  900.     lEof=.F.
  901.     lDoc=.F.
  902. * First find the author
  903.  
  904.     cAuthor=""
  905.     lDone=.F.
  906.     DO WHILE .NOT.lDone
  907. * Author
  908.  
  909.         nDocCnt=0
  910.         cBuffer=ReadLN(@lEof)
  911.         nLineCnt++
  912.         IF nLineCnt%10=0
  913.             @ INFILELINE,52 SAY STR(nLineCnt,5,0)
  914.         ENDIF
  915.         IF AT("Author....",cBuffer)>0
  916.             lDone=.T.
  917.             cAuthor=ALLTRIM(SUBSTR(cBuffer,AT(".:",cBuffer)+2))
  918.             AADD(aAuthorList,cAuthor)
  919.         ENDIF
  920.         lDone=lEof.OR.lDone
  921.         IF lEof
  922.             write_error("Author not found",,,,aDirList[i,F_NAME])
  923.             cAuthor="Unknown"
  924.             FT_FGOTOP()
  925.             nLineCnt=0
  926.             lEof=.F.
  927.         ENDIF
  928.     ENDDO
  929.  
  930. * loop to go through file
  931.  
  932.     DO WHILE .NOT.lEof
  933.  
  934. * Read a line
  935.  
  936.         cBuffer=TRIM(SUBSTR(ReadLN(@lEof),nCommentLen))
  937.         nLineCnt++
  938.         IF nLineCnt%10=0
  939.             @ INFILELINE,52 SAY STR(nLineCnt,5,0)
  940.         ENDIF
  941.  
  942. * check to see if we are in doc mode or getting out of doc mode
  943.  
  944.         IF AT("$DOC$",cBuffer)>0
  945.             IF lDoc
  946.                 write_error("$DOC$ encountered during extraction of Doc";
  947.                     +" at line"+STR(nLinecnt,5,0),,,,aDirList[i,F_NAME])
  948.             ENDIF
  949.             lDoc=.T.
  950.             cBuffer=TRIM(SUBSTR(ReadLN(@lEof),;
  951.                     nCommentLen))
  952.             nLineCnt++
  953.             cCatagory:=cFuncName:=cSeeAlso:=""
  954.             nMode=D_IGNORE
  955.         ELSEIF AT("$END$",cBuffer)>0
  956.             IF .NOT.lDoc
  957.                 write_error("$END$ encountered outside of Doc area at line";
  958.                     +STR(nLinecnt,5,0),,,,aDirList[i,F_NAME])
  959.  
  960.             ELSE
  961. * Add a new entry to our list of files
  962.  
  963.                 IF EMPTY(cCatagory)
  964.                     write_error("Blank Catagory",,,,aDirList[i,F_NAME])
  965.                     cCatagory="Unknown"
  966.                 ENDIF
  967.                 IF EMPTY(cFuncName)
  968.                     write_error("Blank Function Name",,,,aDirList[i,F_NAME])
  969.                     cFuncName="Unknown"
  970.                 ENDIF
  971.                 AADD(aDocInfo,{cCatagory,cFuncName,cOneLine,cFileName})
  972. * Now close down this little piece
  973.                 lDoc=.F.
  974.                 IF nDocCnt>60
  975.                     FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
  976.                     nDocCnt=0
  977.                 ENDIF
  978.                 FWRITE(nWriteHandle,CRLF)
  979.                 FWRITE(nWriteHandle," Source: "+aDirList[i,F_NAME]+CRLF+CRLF)
  980.                 FWRITE(nWriteHandle," Author: "+cAuthor+CRLF)
  981.                 IF .NOT.EMPTY(cSeeAlso)
  982.                     FWRITE(nWriteHandle,"See also:"+cSeeAlso+CRLF)
  983.                 ENDIF
  984.                 FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
  985.                 nDocCnt=0
  986.                 FCLOSE(nWriteHandle)
  987.             ENDIF
  988.             nMode=D_IGNORE
  989.             @ MODULELINE, 33 CLEAR TO MODULELINE, MAXCOL()
  990.         ENDIF
  991.  
  992. * Act on the input
  993.         IF lDoc
  994. * 1) function name
  995.  
  996.             IF AT("$FUNCNAME$",cBuffer)>0
  997.                 cBuffer=ReadLN(@lEof)
  998.                 nLineCnt++
  999. * Save the function name
  1000.                 cFuncName=UPPER(ALLTRIM(SUBSTR(cBuffer,nCommentLen)))
  1001.                 @ MODULELINE, 33 CLEAR TO MODULELINE, MAXCOL()
  1002.                 @ MODULELINE, 33 SAY cFuncName
  1003.  
  1004.                 nMode=D_NORMAL
  1005.  
  1006. * Open a new file
  1007.                 IF AT("FT_",cFuncName)>0
  1008.                     cTemp=SUBSTR(cFuncName,4)
  1009.                 ELSE
  1010.                     cTemp=cFuncName
  1011.                 ENDIF
  1012.  
  1013.                 IF (nEnd:=AT("(",cTemp))>0
  1014.                     cTemp=LEFT(cTemp,nEnd-1)
  1015.                 ENDIF
  1016.                 cFileName=""
  1017.  
  1018. * Strip off any other non-alphabetic/numeric characters
  1019.                 FOR j=1 TO LEN(cTemp)
  1020.                     cChar=SUBSTR(cTemp,j,1)
  1021.                     IF (cChar>="0".AND.cChar<="9").OR.;
  1022.                         (cChar>="A".AND.cChar<="Z").OR.cChar="_"
  1023.                         cFileName+=cChar
  1024.                     ENDIF
  1025.                 NEXT
  1026.  
  1027. * See if file name is present already. If so then modify
  1028.  
  1029.                 cFileName=LEFT(cFileName,8)
  1030.                 nEnd=1
  1031.                 nCount=0
  1032.                 DO WHILE nEnd>0
  1033.                     nEnd=ASCAN(aDocInfo,{|a| a[4]==cFileName+".NGI"})
  1034.                     IF nEnd>0
  1035.  
  1036. * This will break if there are more than 10 files with the same first
  1037. * seven characters. We take our chances.
  1038.  
  1039.                         IF LEN(cFileName)=8
  1040.                             cFileName=STUFF(cFileName,8,1,STR(nCount,1,0))
  1041.                         ELSE
  1042.                             cFileName+=STR(nCount,1,0)
  1043.                         ENDIF
  1044.                         nCount++
  1045.                     ENDIF
  1046.                 ENDDO
  1047. * Add on the extension
  1048.  
  1049.                 cFileName=LEFT(cFileName,8)+".NGI"
  1050.  
  1051.                 nWriteHandle=FCREATE("NGI\"+cFileName)
  1052.                 IF nWriteHandle<1
  1053.                     ? "Error creating",cFileName,".ngi"
  1054.                     write_error("Error creating",,,,cFileName+".ngi")
  1055.                 ENDIF
  1056. * 2) Category
  1057.             ELSEIF AT("$CATEGORY$",cBuffer)>0
  1058.                 cBuffer=ReadLN(@lEof)
  1059.                 nLineCnt++
  1060. * get the catagory
  1061.                 cCatagory=ALLTRIM(SUBSTR(cBuffer,nCommentLen))
  1062.  
  1063. * 3) One line description
  1064.  
  1065.             ELSEIF AT("$ONELINER$",cBuffer)>0
  1066.                 cBuffer=ReadLN(@lEof)
  1067.                 nLineCnt++
  1068.                 cOneLine=ALLTRIM(SUBSTR(cBuffer,nCommentLen))
  1069.                 IF LEN(cOneLine)>LONGONELINE
  1070.                     write_error("OneLine",cOneLine,nLineCnt,LONGONELINE,;
  1071.                         aDirList[i,F_NAME])
  1072.                 ENDIF
  1073.  
  1074. * Now start writing out what we know
  1075.                 IF nDocCnt>60
  1076.                     FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
  1077.                     nDocCnt=0
  1078.                 ENDIF
  1079.  
  1080.                 FWRITE(nWriteHandle,"FUNCTION: "+cFuncName+CRLF)
  1081.                 FWRITE(nWriteHandle," "+cOneLine+CRLF)
  1082.                 FWRITE(nWriteHandle,cBar)
  1083.                 nDocCnt+=3
  1084. * 4) all other stuff
  1085.  
  1086.             ELSE
  1087.  
  1088.                 IF AT("$SYNTAX$",cBuffer)>0
  1089.  
  1090.                     IF nDocCnt>62
  1091.                         FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
  1092.                         nDocCnt=0
  1093.                     ENDIF
  1094.                     FWRITE(nWriteHandle," Syntax:"+CRLF)
  1095.                     nDocCnt++
  1096.                     nMode=D_SYNTAX
  1097.  
  1098.                 ELSEIF AT("$ARGUMENTS$",cBuffer)>0
  1099.  
  1100.                     IF nDocCnt>62
  1101.                         FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
  1102.                         nDocCnt=0
  1103.                     ENDIF
  1104.                     FWRITE(nWriteHandle," Arguments:"+CRLF)
  1105.                     nDocCnt++
  1106.                     nMode=D_ARG
  1107.  
  1108.                 ELSEIF AT("$RETURNS$",cBuffer)>0
  1109.  
  1110.                     IF nDocCnt>62
  1111.                         FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
  1112.                         nDocCnt=0
  1113.                     ENDIF
  1114.                     FWRITE(nWriteHandle," Returns:"+CRLF)
  1115.                     nDocCnt++
  1116.                     nMode=D_NORMAL
  1117.  
  1118.                 ELSEIF AT("$DESCRIPTION$",cBuffer)>0
  1119.  
  1120.                     IF nDocCnt>62
  1121.                         FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
  1122.                         nDocCnt=0
  1123.                     ENDIF
  1124.                     FWRITE(nWriteHandle," Description:"+CRLF)
  1125.                     nDocCnt++
  1126.                     nMode=D_NORMAL
  1127.  
  1128.                 ELSEIF AT("$EXAMPLES$",cBuffer)>0
  1129.  
  1130.                     IF nDocCnt>62
  1131.                         FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
  1132.                         nDocCnt=0
  1133.                     ENDIF
  1134.                     FWRITE(nWriteHandle," Examples:"+CRLF)
  1135.                     nDocCnt++
  1136.                     nMode=D_NORMAL
  1137.  
  1138.                 ELSEIF AT("$SEEALSO$",cBuffer)>0
  1139.                     nMode=D_SEEALSO
  1140.                 ELSEIF AT("$INCLUDE$",cBuffer)>0
  1141.                     nMode=D_INCLUDE
  1142.  
  1143. * All other input is trimmed of comments and sent out
  1144.  
  1145.                 ELSE
  1146.                     IF nMode=D_SYNTAX
  1147.                         IF LEN(cBuffer)>LONGLINE
  1148.                             write_error("Syntax",cBuffer,nLineCnt,;
  1149.                                     LONGLINE,aDirList[i,F_NAME])
  1150.                         ENDIF
  1151.                         IF nDocCnt>62
  1152.                             FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
  1153.                             nDocCnt=0
  1154.                         ENDIF
  1155.                         FWRITE(nWriteHandle," "+cBuffer+CRLF)
  1156.                         nDocCnt++
  1157.                     ELSEIF nMode=D_ARG
  1158.                         IF LEN(cBuffer)>LONGLINE
  1159.                             write_error("Arguments",cBuffer,nLineCnt,;
  1160.                                     LONGLINE,aDirList[i,F_NAME])
  1161.                         ENDIF
  1162.                         IF nDocCnt>62
  1163.                             FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
  1164.                             nDocCnt=0
  1165.                         ENDIF
  1166.                         FWRITE(nWriteHandle,cBuffer+CRLF)
  1167.                         nDocCnt++
  1168.                     ELSEIF nMode=D_NORMAL
  1169.                         IF LEN(cBuffer)>LONGLINE
  1170.                             write_error("General",cBuffer,nLineCnt,;
  1171.                                     LONGLINE,aDirList[i,F_NAME])
  1172.                         ENDIF
  1173.                         IF nDocCnt>62
  1174.                             FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
  1175.                             nDocCnt=0
  1176.                         ENDIF
  1177.                         FWRITE(nWriteHandle,cBuffer+CRLF)
  1178.                         nDocCnt++
  1179.                     ELSEIF nMode=D_SEEALSO
  1180.                         IF .NOT.EMPTY(cBuffer)
  1181.                             cSeeAlso=cBuffer
  1182.                         ENDIF
  1183.                     ELSEIF nMode=D_INCLUDE
  1184.                         IF .NOT.EMPTY(cBuffer)
  1185.                             IF nDocCnt>62
  1186.                                 FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
  1187.                                 nDocCnt=0
  1188.                             ENDIF
  1189.                             FWRITE(nWriteHandle," Header File: ";
  1190.                                 +cBuffer+CRLF)
  1191.                             nDocCnt++
  1192.                         ENDIF
  1193.  
  1194.                     ENDIF
  1195.                 ENDIF
  1196.             ENDIF
  1197.         ENDIF
  1198.     ENDDO
  1199. * Close down the input file
  1200.  
  1201.     FT_FUSE()
  1202. NEXT
  1203.  
  1204.  
  1205. RETURN NIL
  1206.  
  1207. * End of ASCIIfiles
  1208.