home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Press 1997 July
/
Sezamfile97_1.iso
/
msdos
/
clipper
/
ft_doc.arj
/
FT_DOC.PRG
< prev
next >
Wrap
Text File
|
1992-03-13
|
30KB
|
1,208 lines
/*
* File......: FT_DOC.PRG
* Author....: Leo Letendre
* CIS ID....: 73607,233
* Date......: $Date: 11 Feb 1992 20:26:00 $
* Revision..: $Revision: 1.0 $
* Log file..: $Logfile: $
*
* This is an original work by Leo Letendre and is placed in the
* public domain.
*
* Modification history:
* ---------------------
*
* V1.00
* 1/19/92 Initial Version
*
* V1.01
* 3/13/92 Fixed ascii output which had too many form feeds
*/
#include "directry.ch"
#include "fileio.ch"
#include "inkey.ch"
#define INFILELINE 10
#define MODULELINE 12
#define ERRORLINE 20
#define LONGLINE 78
#define LONGONELINE 60
STATIC nReadHandle, nWriteHandle
STATIC aDirList
STATIC aDocInfo:={}
STATIC aLinkInfo:={}
STATIC aAuthorList:={}
*-
/* $DOC$
* $FUNCNAME$
* FT_DOC
* $CATEGORY$
* Documentation
* $ONELINER$
* Extracts documentation from source files
* $SYNTAX$
* FT_DOC [-a] <cLinkName> [<cAtFile>]
* $ARGUMENTS$
* [-a] This flag produces an ascii text of the documentation with
* a form feed between each doc set. Note: must be first if given.
* <cLinkname> The name of the Norton Guides Library linkfile.
* <cAtFile> The file name of a list of files to process. If absent
* then *.PRG, *.C, *.ASM, *.CH are processed.
* $RETURNS$
* NIL
* $DESCRIPTION$
* This routine extracts the documentation out of all of the .PRG,
* .C and .ASM files in the current directory. It creates a series of
* text files containing the documentation which can be used with a lnk
* file to compile and link into the NG file.
*
* The input consists of the link file for the Norton Guide linker,
* NGML. This file consists of commands which identify menu items. This
* program looks at the menu items and the input file for each menu item
* and builds that input file from sources which have the $CATAGORY$ of
* the same name. A batch file called "ASSEMBL.BAT" is created which
* when run will concatenate all of the files produced from the sources
* into files to be compiled by NGC. After compiling NGML is called
* with the link file to link the library. (This assumes that all input
* files for the Norton Guide come from the source code or have already
* been compiled.)
*
* If cAtFile is included in the command line then it is the source
* of file names for processing. Otherwise all .PRG, .C, .ASM, and .CH
* files in the current directory are processed. A subdirectory is
* created in the current directory called NGI. This will contain all
* of the sources used to create the Norton Guide. The files are NOT
* deleted so you can alter then if you want and then run the ASSEMBL
* command. The form of the cAtFile is one file name per line.
*
* The information which is extracted is all that is contained between
* the $DOC$ and the $END$ in the forum toolkit header. It is assumed that
* the order has not been changed from that given in the Toolkit. Some
* variation may be tolerated but I have not tested all possibilities.
* It is also safer to leave a blank line after an entry if you do not
* have anything to put in rather than having two $XXXX$ lines come in
* succession. Also the first occurrence of author is used as the author
* for all routines in the file. If none is found it is listed as unknown.
*
* A log file is produced called FT_DOC.LOG. It contains a listing of
* all routines processed and their respective catagories. A file called
* AUTHOR.TXT is also produced which contains a list of all authors.
* DOCERR.LOG is created which contains all errors encountered during the
* processing. Errors include lines which are too long, catagories not
* found and the like.
*
* NOTE: don't try the program on this source since I haven't made it
* ignore the extra $DOC and $ENDs.
* $EXAMPLES$
* C:>FT_DOC nanfor.lnk
* $SEEALSO$
*
* $INCLUDE$
*
* $END$
*/
FUNCTION FT_DOC(cFlags,cLinkName,cAtFile)
* LOCAL variables:
LOCAL aExtensions:={"*.PRG","*.C","*.ASM","*.CH"}
LOCAL i, nItem, cBatName
LOCAL lAscii
LOCAL nSec1
*
* Entry Point
*
nSec1=SECONDS()
* Delete log file if present
IF FILE("DOCERR.LOG")
DELETE FILE "DOCERR.LOG"
ENDIF
* See if flag is there
IF .NOT.EMPTY(cFlags)
IF UPPER(cFlags)=="-A".OR.UPPER(cFlags)=="/A"
lAscii=.T.
ELSE
lAscii=.F.
cAtFIle=cLinkName
cLinkName=cFlags
ENDIF
ENDIF
* Get the linkfile name and get the info in it
IF cLinkName=NIL
? "Syntax: MAKENG [-a] <linkname> [<ifile.]"
? " Where -a creates an ascii file instead of a Norton Guide"
? " linkname is the name of the Norton Guide Link file"
? " iFile is a file containing a list of files to process"
? " otherwise *.PRG, *.C, *.ASM and *.CH are used"
RETURN NIL
ENDIF
* check to see if input files are present
IF .NOT.FILE(cLinkName)
? "Link file Not Found:",cLinkName
RETURN NIL
ENDIF
IF .NOT.EMPTY(cAtFIle).AND..NOT.FILE(cAtFile)
? "Indirect file Not Found:",cAtFile
RETURN NIL
ENDIF
CLEAR SCREEN
SET CURSOR OFF
fill_Link_info(cLinkName)
* See if ngi subdirectory is present
IF EMPTY(DIRECTORY("NGI.*","D"))
FT_MKDIR("NGI")
ENDIF
IF cAtFile=NIL // use all files in directory
* Loop through each of the types of files
FOR i=1 TO LEN(aExtensions)
* Get the list of
aDirList=DIRECTORY(aExtensions[i])
* If there are any files then process them
IF LEN(aDirList)>0
IF lAscii
ASCIIFiles()
ELSE
ProcessFiles()
ENDIF
ENDIF
NEXT
ELSE
* an indirect file was given so read it and use it
aDirList=ReadAtFile(cAtFile)
* If there are any files then process them
IF LEN(aDirList)>0
IF lAscii
ASCIIFILES()
ELSE
ProcessFiles()
ENDIF
ENDIF
ENDIF
* Now build text files for norton compiler based upon link file
* first sort based upon catagory and filename. Not Fast but easy.
@ INFILELINE,0 CLEAR TO INFILELINE,MAXCOL()
@ MODULELINE,0 CLEAR TO MODULELINE,MAXCOL()
@ INFILELINE,30 SAY "Sorting input files"
ASORT(aDocInfo,,,{|a,b| UPPER(a[1]+" "+a[2])<UPPER(b[1]+" "+b[2])})
* Now actually build the info
@ INFILELINE,0 CLEAR TO INFILELINE,MAXCOL()
@ INFILELINE,30 SAY "Assembling "+IIF(lAscii,"documentation","NG");
+" input files"
IF FILE("assembl.bat")
DELETE FILE "assembl.bat"
ENDIF
SET ALTERNATE TO "assembl.bat"
SET ALTERNATE ON
SET CONSOLE OFF
? "@Echo OFF"
? "ECHO Assembling input files"
FOR i=1 TO LEN(aDocInfo)
* Find match
nItem=ASCAN(aLinkInfo,{|a| UPPER(ALLTRIM(a[1]))==UPPER(ALLTRIM(aDocInfo[i,1]))})
IF nItem>0
IF i=1.OR..NOT.(ALLTRIM(aDocInfo[i-1,1])==ALLTRIM(aDocInfo[i,1]))
* Make the first copy
? "COPY NGI\"+ALLTRIM(aDocInfo[i,4]),aLinkinfo[nItem,2]
ELSE
* This may be slow but I don't have to worry about line length
? "TYPE NGI\"+ALLTRIM(aDocInfo[i,4])+" >>"+aLinkinfo[nItem,2]
ENDIF
aLinkInfo[nItem,3]=.T.
ELSE
* Write the error message
SET ALTERNATE TO
SET ALTERNATE OFF
SET CONSOLE ON
write_error("Catagory not found: "+aDocInfo[i,1],,,,aDocInfo[i,4])
@ ERRORLINE,0 CLEAR TO ERRORLINE,MAXCOL()
@ ERRORLINE,20 SAY "Catagory not found: "+aDocInfo[i,1]+" in "+aDocInfo[i,4]
SET ALTERNATE TO "assembl.bat" ADDITIVE
SET ALTERNATE ON
SET CONSOLE OFF
ENDIF
NEXT
* Delete old files
/*FOR i=1 TO LEN(aLinkInfo)
IF FILE(aLinkInfo[i,2]).AND.aLinkInfo[i,3]
DELETE FILE (aLinkInfo[i,2])
ENDIF
NEXT
*/
* Now assemble the output
IF .NOT. lAscii
? "REM Compile the sources"
? "Echo Compiling the sources"
FOR i=1 TO LEN(aLinkInfo)
IF aLinkInfo[i,3]
? "NGC ",aLinkInfo[i,2]
ENDIF
NEXT
? "REM Link the files"
? "Echo Linking library"
? "NGML",cLinkName
? " "
* Send out list of files
@ INFILELINE,0 CLEAR TO INFILELINE,MAXCOL()
@ INFILELINE,30 SAY "Writing summary file"
ENDIF
SET ALTERNATE TO "FT_DOC.LOG"
SET ALTERNATE ON
SET CONSOLE OFF
FOR i=1 TO LEN(aDocInfo)
? PAD(aDocInfo[i,1],15),PAD(aDocInfo[i,2],15),PAD(aDocInfo[i,4],15)
NEXT
* Send out list of authors
@ INFILELINE,0 CLEAR TO INFILELINE,MAXCOL()
@ INFILELINE,30 SAY "Writing Author file"
* sort the list
ASORT(aAuthorList,,,{|a,b| UPPER(a)<UPPER(b)})
* Now write it out
SET ALTERNATE TO "author.txt"
SET ALTERNATE ON
SET CONSOLE OFF
? aAuthorList[1]
FOR i=2 TO LEN(aAuthorList)
IF aAuthorList[i]<>aAuthorList[i-1]
? aAuthorList[i]
ENDIF
NEXT
SET CONSOLE ON
SET ALTERNATE OFF
SET ALTERNATE TO
@MAXROW()-1,0 SAY "Total Time = "+STR(SECONDS()-nSec1)
@MAXROW(),0 SAY "Execute ASSEMBL.BAT to compile and link Guides"
* Return to caller
RETURN NIL
* End of MAIN()
*+
STATIC FUNCTION ProcessFiles
*
* This routine and all accompaning database structures are
* Copyright (C) 1992 Leo J. Letendre.
*
* Purpose: Process each of the files in the directory
*
* Modification History:
* Version Date Who Notes
* V1.00 1/19/92 LJL Initial Version
*
* Calling parameters: None
*
* Notes: None
*-
* LOCAL variables:
#define D_NORMAL 1
#define D_ARG 2
#define D_SYNTAX 3
#define D_IGNORE 4
#define D_SEEALSO 5
#define D_INCLUDE 6
LOCAL i, j, nFiles:=LEN(aDirList)
LOCAL nCommentLen
LOCAL lEof, lDoc, lDone
LOCAL cBuffer
LOCAL nEnd, nCount
LOCAL CRLF:=CHR(13) + CHR(10)
LOCAL cBar:="──────────────────────────────────────────────────────────────────────────────"+CRLF
LOCAL nMode
LOCAL cAuthor
LOCAL cFuncName
LOCAL cOneLine
LOCAL cCatagory
LOCAL cFileName
LOCAL nLineCnt
LOCAL cSeeAlso
LOCAL cTemp, cChar
*
* Entry Point
*
* Put up information labels
@ INFILELINE, 20 SAY "Extracting: "
@ MODULELINE, 20 SAY "Documenting: "
* loop through all of the files
FOR i=1 TO nFiles
* Open file for input
nCommentLen:=IIF(AT("*.ASM",UPPER(aDirList[i,F_NAME]))>0,2,3)
nReadHandle=FT_FUSE(aDirList[i,F_NAME])
@ INFILELINE,33 CLEAR TO INFILELINE, MAXCOL()
@ INFILELINE,33 SAY PAD(aDirList[i,F_NAME],12)+" Line:"
@ MODULELINE,33 CLEAR TO MODULELINE, MAXCOL()
nLineCnt=0
IF nReadHandle<0
write_error("Can't open file: (Dos Error "+STR(FERROR())+")",,,,aDirList[i,F_NAME])
@ ERRORLINE,0 CLEAR TO ERRORLINE,MAXCOL()
@ ERRORLINE,20 SAY "Can't open file: (Dos Error "+STR(FERROR())+") File="+aDirList[i,F_NAME]
LOOP
ENDIF
lEof=.F.
lDoc=.F.
* First find the author
cAuthor=""
lDone=.F.
DO WHILE .NOT.lDone
* Author
cBuffer=ReadLN(@lEof)
nLineCnt++
IF nLineCnt%10=0
@ INFILELINE,52 SAY STR(nLineCnt,5,0)
ENDIF
IF AT("Author....",cBuffer)>0
lDone=.T.
cAuthor=ALLTRIM(SUBSTR(cBuffer,AT(".:",cBuffer)+2))
AADD(aAuthorList,cAuthor)
ENDIF
lDone=lEof.OR.lDone
IF lEof
write_error("Author not found",,,,aDirList[i,F_NAME])
cAuthor="Unknown"
FT_FGOTOP()
nLineCnt=0
lEof=.F.
ENDIF
ENDDO
* loop to go through file
DO WHILE .NOT.lEof
* Read a line
cBuffer=TRIM(SUBSTR(ReadLN(@lEof),nCommentLen))
nLineCnt++
IF nLineCnt%10=0
@ INFILELINE,52 SAY STR(nLineCnt,5,0)
ENDIF
* check to see if we are in doc mode or getting out of doc mode
IF AT("$DOC$",cBuffer)>0
IF lDoc
write_error("$DOC$ encountered during extraction of Doc";
+" at line"+STR(nLinecnt,5,0),,,,aDirList[i,F_NAME])
ENDIF
lDoc=.T.
cBuffer=TRIM(SUBSTR(ReadLN(@lEof),;
nCommentLen))
nLineCnt++
cCatagory:=cFuncName:=cSeeAlso:=""
nMode=D_IGNORE
ELSEIF AT("$END$",cBuffer)>0
IF .NOT.lDoc
write_error("$END$ encountered outside of Doc area at line";
+STR(nLinecnt,5,0),,,,aDirList[i,F_NAME])
ELSE
* Add a new entry to our list of files
IF EMPTY(cCatagory)
write_error("Blank Catagory",,,,aDirList[i,F_NAME])
cCatagory="Unknown"
ENDIF
IF EMPTY(cFuncName)
write_error("Blank Function Name",,,,aDirList[i,F_NAME])
cFuncName="Unknown"
ENDIF
AADD(aDocInfo,{cCatagory,cFuncName,cOneLine,cFileName})
* Now close down this little piece
lDoc=.F.
FWRITE(nWriteHandle,CRLF)
FWRITE(nWriteHandle," ^bSource:^b "+aDirList[i,F_NAME];
+CRLF+CRLF)
FWRITE(nWriteHandle," ^bAuthor:^b "+cAuthor+CRLF)
IF .NOT.EMPTY(cSeeAlso)
FWRITE(nWriteHandle,"!seealso:"+cSeeAlso+CRLF)
ENDIF
FCLOSE(nWriteHandle)
nMode=D_IGNORE
ENDIF
@ MODULELINE, 33 CLEAR TO MODULELINE, MAXCOL()
ENDIF
* Act on the input
IF lDoc
* 1) function name
IF AT("$FUNCNAME$",cBuffer)>0
cBuffer=ReadLN(@lEof)
nLineCnt++
* Save the function name
cFuncName=UPPER(ALLTRIM(SUBSTR(cBuffer,nCommentLen)))
@ MODULELINE, 33 CLEAR TO MODULELINE, MAXCOL()
@ MODULELINE, 33 SAY cFuncName
nMode=D_NORMAL
* Open a new file
IF AT("FT_",cFuncName)>0
cTemp=SUBSTR(cFuncName,4)
ELSE
cTemp=cFuncName
ENDIF
IF (nEnd:=AT("(",cTemp))>0
cTemp=LEFT(cTemp,nEnd-1)
ENDIF
cFileName=""
* Strip off any other non-alphabetic/numeric characters
FOR j=1 TO LEN(cTemp)
cChar=SUBSTR(cTemp,j,1)
IF (cChar>="0".AND.cChar<="9").OR.;
(cChar>="A".AND.cChar<="Z").OR.cChar="_"
cFileName+=cChar
ENDIF
NEXT
* See if file name is present already. If so then modify
cFileName=LEFT(cFileName,8)
nEnd=1
nCount=0
DO WHILE nEnd>0
nEnd=ASCAN(aDocInfo,{|a| a[4]==cFileName+".NGI"})
IF nEnd>0
* This will break if there are more than 10 files with the same first
* seven characters. We take our chances.
IF LEN(cFileName)=8
cFileName=STUFF(cFileName,8,1,STR(nCount,1,0))
ELSE
cFileName+=STR(nCount,1,0)
ENDIF
nCount++
ENDIF
ENDDO
* Add on the extension
cFileName=LEFT(cFileName,8)+".NGI"
nWriteHandle=FCREATE("NGI\"+cFileName)
IF nWriteHandle<1
? "Error creating",cFileName,".ngi"
write_error("Error creating",,,,cFileName+".ngi")
ENDIF
* 2) Category
ELSEIF AT("$CATEGORY$",cBuffer)>0
cBuffer=ReadLN(@lEof)
nLineCnt++
* get the catagory
cCatagory=ALLTRIM(SUBSTR(cBuffer,nCommentLen))
* 3) One line description
ELSEIF AT("$ONELINER$",cBuffer)>0
cBuffer=ReadLN(@lEof)
nLineCnt++
cOneLine=ALLTRIM(SUBSTR(cBuffer,nCommentLen))
IF LEN(cOneLine)>LONGONELINE
write_error("OneLine",cOneLine,nLineCnt,LONGONELINE,;
aDirList[i,F_NAME])
ENDIF
* Now start writing out what we know
FWRITE(nWriteHandle,"!short: "+PAD(cFuncName,17)+cOneLine+CRLF)
FWRITE(nWriteHandle," ^b"+cFuncName+CRLF)
FWRITE(nWriteHandle," "+cOneLine+CRLF)
FWRITE(nWriteHandle,cBar)
* 4) all other stuff
ELSE
IF AT("$SYNTAX$",cBuffer)>0
FWRITE(nWriteHandle," ^bSyntax"+CRLF)
nMode=D_SYNTAX
ELSEIF AT("$ARGUMENTS$",cBuffer)>0
FWRITE(nWriteHandle," ^bArguments"+CRLF)
nMode=D_ARG
ELSEIF AT("$RETURNS$",cBuffer)>0
FWRITE(nWriteHandle," ^bReturns"+CRLF)
nMode=D_NORMAL
ELSEIF AT("$DESCRIPTION$",cBuffer)>0
FWRITE(nWriteHandle," ^bDescription"+CRLF)
nMode=D_NORMAL
ELSEIF AT("$EXAMPLES$",cBuffer)>0
FWRITE(nWriteHandle," ^bExamples"+CRLF)
nMode=D_NORMAL
ELSEIF AT("$SEEALSO$",cBuffer)>0
nMode=D_SEEALSO
ELSEIF AT("$INCLUDE$",cBuffer)>0
nMode=D_INCLUDE
* All other input is trimmed of comments and sent out
ELSE
IF nMode=D_SYNTAX
IF LEN(cBuffer)>LONGLINE
write_error("Syntax",cBuffer,nLineCnt,;
LONGLINE,aDirList[i,F_NAME])
ENDIF
FWRITE(nWriteHandle,"^a1f "+cBuffer+CRLF)
ELSEIF nMode=D_ARG
IF LEN(cBuffer)>LONGLINE
write_error("Arguments",cBuffer,nLineCnt,;
LONGLINE,aDirList[i,F_NAME])
ENDIF
cBuffer=STRTRAN(cBuffer,"<","^b<",1)
cBuffer=STRTRAN(cBuffer,">",">^b",1)
FWRITE(nWriteHandle,cBuffer+CRLF)
ELSEIF nMode=D_NORMAL
IF LEN(cBuffer)>LONGLINE
write_error("General",cBuffer,nLineCnt,;
LONGLINE,aDirList[i,F_NAME])
ENDIF
FWRITE(nWriteHandle,cBuffer+CRLF)
ELSEIF nMode=D_SEEALSO
IF .NOT.EMPTY(cBuffer)
cSeeAlso=cBuffer
ENDIF
ELSEIF nMode=D_INCLUDE
* read next line
IF .NOT.EMPTY(cBuffer)
FWRITE(nWriteHandle," ^bHeader File:^b ";
+cBuffer+CRLF+CRLF)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDDO
* Close down the input file
FT_FUSE()
NEXT
RETURN NIL
* End of file process files
*+
FUNCTION fill_link_info(cLinkName)
*
* This routine and all accompaning database structures are
* Copyright (C) 1992 Leo J. Letendre.
*
* Purpose: read the link information to learn how to assemble database files
*
* Modification History:
* Version Date Who Notes
* V1.00 1/22/92 LJL Initial Version
*
* Calling parameters: cLinkName - The name of the link file
*
* Notes: looks for the !menu command and then reads the lines after it to
* get the catagories and filenames associated with each.
*-
* LOCAL variables:
LOCAL cBuffer, lEof, cSpace
LOCAL cCatagory, cFile
LOCAL lMenuMode:=.F.
*
* Entry Point
*
nReadHandle=FT_FUSE(cLinkName)
lEof=.F.
DO WHILE .NOT. lEof
* Read a line
cBuffer=UPPER(ReadLN(@lEof))
* Does it have a !menu?
IF AT("!MENU",cBuffer)>0
lMenuMode=.T.
ELSEIF LEFT(cBuffer,1)="!"
lMenuMode=.F.
ENDIF
* If we are in menu mode and the line has information on it then parse it
cBuffer=ALLTRIM(cBuffer)
IF .NOT.EMPTY(cBuffer)
cSpace=AT(" ",cBuffer)
cCatagory=UPPER(RTRIM(LEFT(cBuffer,cSpace-1)))
cFile=UPPER(LTRIM(SUBSTR(cBuffer,cSpace)))
cFile=STRTRAN(cFile,".NGO",".TXT")
AADD(aLinkInfo,{cCatagory,cFile,.F.})
ENDIF
ENDDO
* Close the file
FT_FUSE()
* Return to caller
RETURN NIL
* End of fill_link_info
*+
STATIC FUNCTION ReadAtFile(cAtFile)
*
* This routine and all accompaning database structures are
* Copyright (C) 1992 Leo J. Letendre.
*
* Purpose: read in the users list of files to act on
*
* Modification History:
* Version Date Who Notes
* V1.00 1/1/92 LJL Initial Version
*
* Calling parameters: cAtFile - The name of the file containing a list of
* files to be processed
*
* Returns: an array containing information that looks like it came
* from DIRECTORY() but only has the name present.
*
* Notes:
*-
* LOCAL variables:
LOCAL aDirList:={}
LOCAL cBuffer, lEof, nCount:=0
*
* Entry Point
*
IF FT_FUSE(cAtFile)<>NIL
* Read each line
lEof=.F.
DO WHILE .NOT. lEof
cBuffer=ALLTRIM(ReadLN(@lEof))
IF .NOT. EMPTY(cBuffer)
AADD(aDirList,ARRAY(F_LEN))
nCount++
aDirList[nCount,F_NAME]=UPPER(cBuffer)
ENDIF
ENDDO
ENDIF
FT_FUSE()
RETURN aDirList
* End of ReadAtFile
STATIC FUNCTION write_error(cDesc, cBadLine, nLineCnt, nMax, cFile)
* This routine will send error messages to the error log - MAKENG.LOG
*
* Calling parameters: cDesc - Description of info being written
* cBadLine - The offending line - IF NIL then just
* output cDesc and filename
* nLineCnt - The line number of the bad line
* nMax - The maximum length of the bad line
* cFile - The file currently being processed
*
* Returns: NIL
*
* Entry point
*
* Point output to the log file
SET ALTERNATE TO "DOCERR.LOG" ADDITIVE
SET CONSOLE OFF
SET ALTERNATE ON
* Send out the output
IF cBadLine=NIL
? cDesc,"in file",cFile
? " "
ELSE
? "Line too long in file",cFile,"at line",ALLTRIM(STR(nLineCnt,10,0))
? "Reading",cDesc,"information when line greater than",STR(nMax,2,0),"encountered:"
? cBadLine
? " "
ENDIF
* Turn off the log file and return
SET ALTERNATE OFF
SET CONSOLE ON
SET ALTERNATE TO
RETURN NIL
* End of Write_Error
/***
* ReadLn( lEof ) --> cBuffer
*
* Read a line from the currently open file
*
* Parameters: lEof - Passed by reference - Logical indicating end of file
*
* Returns: The next line in the file without delimiters
*
*/
FUNCTION ReadLN( leof )
LOCAL cBuffer := ""
cBuffer=FT_FREADLN()
FT_FSKIP(1)
lEof=FT_FEOF()
RETURN cBuffer
* End of ReadLN
*+
STATIC FUNCTION ASCIIFiles
*
* This routine and all accompaning database structures are
* Copyright (C) 1992 Leo J. Letendre.
*
* Purpose: Process each of the files in the directory making an ascii file
*
* Modification History:
* Version Date Who Notes
* V1.00 1/19/92 LJL Initial Version
*
* Calling parameters: None
*
* Notes: None
*-
* LOCAL variables:
LOCAL i, j, nFiles:=LEN(aDirList)
LOCAL nCommentLen
LOCAL lEof, lDoc, lDone
LOCAL cBuffer
LOCAL nEnd, nCount
LOCAL CRLF:=CHR(13) + CHR(10)
LOCAL cBar:="──────────────────────────────────────────────────────────────────────────────"+CRLF
LOCAL nMode
LOCAL cAuthor
LOCAL cFuncName
LOCAL cOneLine
LOCAL cCatagory
LOCAL cFileName
LOCAL nLineCnt
LOCAL cSeeAlso
LOCAL cTemp, cChar
LOCAL nDocCnt
*
* Entry Point
*
* Put up information labels
@ INFILELINE, 20 SAY "Extracting: "
@ MODULELINE, 20 SAY "Documenting: "
* loop through all of the files
FOR i=1 TO nFiles
* Open file for input
nCommentLen:=IIF(AT("*.ASM",UPPER(aDirList[i,F_NAME]))>0,2,3)
nReadHandle=FT_FUSE(aDirList[i,F_NAME])
@ INFILELINE,33 CLEAR TO INFILELINE, MAXCOL()
@ INFILELINE,33 SAY PAD(aDirList[i,F_NAME],12)+" Line:"
@ MODULELINE,33 CLEAR TO MODULELINE, MAXCOL()
nLineCnt=0
IF nReadHandle<0
write_error("Can't open file: (Dos Error "+STR(FERROR())+")",,,,aDirList[i,F_NAME])
@ ERRORLINE,0 CLEAR TO ERRORLINE,MAXCOL()
@ ERRORLINE,20 SAY "Can't open file: (Dos Error "+STR(FERROR())+") File="+aDirList[i,F_NAME]
LOOP
ENDIF
lEof=.F.
lDoc=.F.
* First find the author
cAuthor=""
lDone=.F.
DO WHILE .NOT.lDone
* Author
nDocCnt=0
cBuffer=ReadLN(@lEof)
nLineCnt++
IF nLineCnt%10=0
@ INFILELINE,52 SAY STR(nLineCnt,5,0)
ENDIF
IF AT("Author....",cBuffer)>0
lDone=.T.
cAuthor=ALLTRIM(SUBSTR(cBuffer,AT(".:",cBuffer)+2))
AADD(aAuthorList,cAuthor)
ENDIF
lDone=lEof.OR.lDone
IF lEof
write_error("Author not found",,,,aDirList[i,F_NAME])
cAuthor="Unknown"
FT_FGOTOP()
nLineCnt=0
lEof=.F.
ENDIF
ENDDO
* loop to go through file
DO WHILE .NOT.lEof
* Read a line
cBuffer=TRIM(SUBSTR(ReadLN(@lEof),nCommentLen))
nLineCnt++
IF nLineCnt%10=0
@ INFILELINE,52 SAY STR(nLineCnt,5,0)
ENDIF
* check to see if we are in doc mode or getting out of doc mode
IF AT("$DOC$",cBuffer)>0
IF lDoc
write_error("$DOC$ encountered during extraction of Doc";
+" at line"+STR(nLinecnt,5,0),,,,aDirList[i,F_NAME])
ENDIF
lDoc=.T.
cBuffer=TRIM(SUBSTR(ReadLN(@lEof),;
nCommentLen))
nLineCnt++
cCatagory:=cFuncName:=cSeeAlso:=""
nMode=D_IGNORE
ELSEIF AT("$END$",cBuffer)>0
IF .NOT.lDoc
write_error("$END$ encountered outside of Doc area at line";
+STR(nLinecnt,5,0),,,,aDirList[i,F_NAME])
ELSE
* Add a new entry to our list of files
IF EMPTY(cCatagory)
write_error("Blank Catagory",,,,aDirList[i,F_NAME])
cCatagory="Unknown"
ENDIF
IF EMPTY(cFuncName)
write_error("Blank Function Name",,,,aDirList[i,F_NAME])
cFuncName="Unknown"
ENDIF
AADD(aDocInfo,{cCatagory,cFuncName,cOneLine,cFileName})
* Now close down this little piece
lDoc=.F.
IF nDocCnt>60
FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
nDocCnt=0
ENDIF
FWRITE(nWriteHandle,CRLF)
FWRITE(nWriteHandle," Source: "+aDirList[i,F_NAME]+CRLF+CRLF)
FWRITE(nWriteHandle," Author: "+cAuthor+CRLF)
IF .NOT.EMPTY(cSeeAlso)
FWRITE(nWriteHandle,"See also:"+cSeeAlso+CRLF)
ENDIF
FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
nDocCnt=0
FCLOSE(nWriteHandle)
ENDIF
nMode=D_IGNORE
@ MODULELINE, 33 CLEAR TO MODULELINE, MAXCOL()
ENDIF
* Act on the input
IF lDoc
* 1) function name
IF AT("$FUNCNAME$",cBuffer)>0
cBuffer=ReadLN(@lEof)
nLineCnt++
* Save the function name
cFuncName=UPPER(ALLTRIM(SUBSTR(cBuffer,nCommentLen)))
@ MODULELINE, 33 CLEAR TO MODULELINE, MAXCOL()
@ MODULELINE, 33 SAY cFuncName
nMode=D_NORMAL
* Open a new file
IF AT("FT_",cFuncName)>0
cTemp=SUBSTR(cFuncName,4)
ELSE
cTemp=cFuncName
ENDIF
IF (nEnd:=AT("(",cTemp))>0
cTemp=LEFT(cTemp,nEnd-1)
ENDIF
cFileName=""
* Strip off any other non-alphabetic/numeric characters
FOR j=1 TO LEN(cTemp)
cChar=SUBSTR(cTemp,j,1)
IF (cChar>="0".AND.cChar<="9").OR.;
(cChar>="A".AND.cChar<="Z").OR.cChar="_"
cFileName+=cChar
ENDIF
NEXT
* See if file name is present already. If so then modify
cFileName=LEFT(cFileName,8)
nEnd=1
nCount=0
DO WHILE nEnd>0
nEnd=ASCAN(aDocInfo,{|a| a[4]==cFileName+".NGI"})
IF nEnd>0
* This will break if there are more than 10 files with the same first
* seven characters. We take our chances.
IF LEN(cFileName)=8
cFileName=STUFF(cFileName,8,1,STR(nCount,1,0))
ELSE
cFileName+=STR(nCount,1,0)
ENDIF
nCount++
ENDIF
ENDDO
* Add on the extension
cFileName=LEFT(cFileName,8)+".NGI"
nWriteHandle=FCREATE("NGI\"+cFileName)
IF nWriteHandle<1
? "Error creating",cFileName,".ngi"
write_error("Error creating",,,,cFileName+".ngi")
ENDIF
* 2) Category
ELSEIF AT("$CATEGORY$",cBuffer)>0
cBuffer=ReadLN(@lEof)
nLineCnt++
* get the catagory
cCatagory=ALLTRIM(SUBSTR(cBuffer,nCommentLen))
* 3) One line description
ELSEIF AT("$ONELINER$",cBuffer)>0
cBuffer=ReadLN(@lEof)
nLineCnt++
cOneLine=ALLTRIM(SUBSTR(cBuffer,nCommentLen))
IF LEN(cOneLine)>LONGONELINE
write_error("OneLine",cOneLine,nLineCnt,LONGONELINE,;
aDirList[i,F_NAME])
ENDIF
* Now start writing out what we know
IF nDocCnt>60
FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
nDocCnt=0
ENDIF
FWRITE(nWriteHandle,"FUNCTION: "+cFuncName+CRLF)
FWRITE(nWriteHandle," "+cOneLine+CRLF)
FWRITE(nWriteHandle,cBar)
nDocCnt+=3
* 4) all other stuff
ELSE
IF AT("$SYNTAX$",cBuffer)>0
IF nDocCnt>62
FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
nDocCnt=0
ENDIF
FWRITE(nWriteHandle," Syntax:"+CRLF)
nDocCnt++
nMode=D_SYNTAX
ELSEIF AT("$ARGUMENTS$",cBuffer)>0
IF nDocCnt>62
FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
nDocCnt=0
ENDIF
FWRITE(nWriteHandle," Arguments:"+CRLF)
nDocCnt++
nMode=D_ARG
ELSEIF AT("$RETURNS$",cBuffer)>0
IF nDocCnt>62
FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
nDocCnt=0
ENDIF
FWRITE(nWriteHandle," Returns:"+CRLF)
nDocCnt++
nMode=D_NORMAL
ELSEIF AT("$DESCRIPTION$",cBuffer)>0
IF nDocCnt>62
FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
nDocCnt=0
ENDIF
FWRITE(nWriteHandle," Description:"+CRLF)
nDocCnt++
nMode=D_NORMAL
ELSEIF AT("$EXAMPLES$",cBuffer)>0
IF nDocCnt>62
FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
nDocCnt=0
ENDIF
FWRITE(nWriteHandle," Examples:"+CRLF)
nDocCnt++
nMode=D_NORMAL
ELSEIF AT("$SEEALSO$",cBuffer)>0
nMode=D_SEEALSO
ELSEIF AT("$INCLUDE$",cBuffer)>0
nMode=D_INCLUDE
* All other input is trimmed of comments and sent out
ELSE
IF nMode=D_SYNTAX
IF LEN(cBuffer)>LONGLINE
write_error("Syntax",cBuffer,nLineCnt,;
LONGLINE,aDirList[i,F_NAME])
ENDIF
IF nDocCnt>62
FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
nDocCnt=0
ENDIF
FWRITE(nWriteHandle," "+cBuffer+CRLF)
nDocCnt++
ELSEIF nMode=D_ARG
IF LEN(cBuffer)>LONGLINE
write_error("Arguments",cBuffer,nLineCnt,;
LONGLINE,aDirList[i,F_NAME])
ENDIF
IF nDocCnt>62
FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
nDocCnt=0
ENDIF
FWRITE(nWriteHandle,cBuffer+CRLF)
nDocCnt++
ELSEIF nMode=D_NORMAL
IF LEN(cBuffer)>LONGLINE
write_error("General",cBuffer,nLineCnt,;
LONGLINE,aDirList[i,F_NAME])
ENDIF
IF nDocCnt>62
FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
nDocCnt=0
ENDIF
FWRITE(nWriteHandle,cBuffer+CRLF)
nDocCnt++
ELSEIF nMode=D_SEEALSO
IF .NOT.EMPTY(cBuffer)
cSeeAlso=cBuffer
ENDIF
ELSEIF nMode=D_INCLUDE
IF .NOT.EMPTY(cBuffer)
IF nDocCnt>62
FWRITE(nWriteHandle,CHR(K_CTRL_L)+CRLF)
nDocCnt=0
ENDIF
FWRITE(nWriteHandle," Header File: ";
+cBuffer+CRLF)
nDocCnt++
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDDO
* Close down the input file
FT_FUSE()
NEXT
RETURN NIL
* End of ASCIIfiles