main logo
Subject: RE: Agle Programming
Author: "Bill Arnold"
Posted: 2006/09/29 13:30:36
 
View Entire Thread
New Search



> Is there a way to have the Help builder pull in the 'header' block of
> comments of the code?
>
> -Charlie


Hi Charlie,

Here's a utility I wrote to do this, below.


Bill


* COMGRAB.PRG


* This program will extract comment lines from the top of all prgs in
* a specified folder, and create a set of corresponding comment (doc)
files
* for each prg in a target folder.

* Comment lines are lines that begin with an asterisk. Interspersed
blank
* lines among comment lines are taken with comment lines.

* Scanning begins with the 1st line in each prg, and ends when a line
* not containing an asterisk (or blank) is found.

* The caller provides the name of the folder containing the prgs and the
* name of the folder to contain the result extraction files.

* Each prg in the input folder will result in a .TXT file in the target
folder.
* If a prg does not contain comment lines at the top (before the 1st
instruction),
* a comment file with only the prg name and today's date/time will be
created.


* Change log:

* 6-26-02 wja initial development


parameters csourcelib,ctargetlib

* to test: do comgrab with 'c:\grab','c:\comments'

* There are 2 parameters: the folder containing the source programs, and
the
* folder to contain the extracted comment files. For each program in
* the source program file, a corresponding file is created (or replaced)
* in the target folder.

* If the input (programs) folder name is not provided, the operator is
* prompted to point to it.

* If the output folder name is not provided, C:\COMMENTS is used by
default.
* If an output folder name is provided, and it doesn't exist, it is
created.

* Programs are stored as variable length ASCII text files. CR/LF
sequences
* separate the lines of the prg.



public ccursrc,ccurtgt,ldoneflag,cprglist,nprgcount,ccomments

cstartdir = curdir() && save current folder on entry
nprgsdone = 0 && number of prgs scanned

do checkparms with csourcelib,ctargetlib && make sure we have
source/target folders
if ldoneflag && if anything is wrong
return && can't continue
endif

* We have valid source and target folder names

* Load an array (CPRGLIST) with an entry for each prg in folder

do loadplist && load cprglist array with program
names
if ldoneflag && if anything is wrong
return && can't continue
endif

* On return from LOADPLIST, CPRGLIST contains 1 row for each prg in the
folder
* and NPRGCOUNT contains the count of programs (rows) in the CPRGLIST
array.


* Here are calls to SCANPRG and WRITECOMF for each prg in the source
folder.
* Programs without comments will be represented in the output folder,
because
* at the very least, a header line is built for each prg before the scan
* starts.

* SCANPRG loads the CCOMMENTS variable with a header and extracted
comment lines.
* WRITECOMF writes CCOMMENTS to the output folder.


for ncurprg = 1 to nprgcount && loop for each prg in CPRGLIST
array

do scanprg with cprglist(ncurprg,1) && scan the first/next program
for comments
do writecomf with ccurtgt,cprglist(ncurprg,1) && create
[programname].txt in target folder

endfor

cd (cstartdir) && restore opers current folder

nprgsdone = ncurprg - 1 && number of prgs actually scanned

=messagebox("Scanning completed. "+transform(nprgsdone,'999,999,999')+"
comment files have been ;
placed into "+trim(ccurtgt)+" for programs in
"+trim(ccursrc),0,"Comments grabber")

return
*
------------------------------------------------------------------------
procedure writecomf && write CCOMMENTS to prgname.txt in
tgt folder
parameters ctgtfolder,csrcname && target folder name, source prg file
name

* The output comments file is named using the source program file name +
the
* file type .TXT.

* For example, MYPROG.PRG will get a counterpart comments file named
MYPROG.TXT

* If the output (comments) file already exists, it will automatically be
replaced

ndotloc = at('.',csrcname)
if empty(ndotloc)
ctgtname = alltrim(csrcname)+'.txt'
else
ctgtname = stuff(csrcname,ndotloc,4,'.txt')
endif

ctgtname = lower(trim(ctgtfolder)+'\'+ctgtname) && e.g.
c:\comments\myprg.txt

* If the target .TXT file exists, overlay it

set safety off
strtofile(ccomments,ctgtname) && create the comments counterpart file
for this prg
set safety on

return
*
------------------------------------------------------------------------
procedure scanprg && scan and extact comments from ctheprg
parameters ctheprg


* This rtn performs the scanning operation against the current program
(CTHEPRG)

* The scanning operation itself is basically a top to bottom reading of
the
* lines of the current program, checking each line to see if it's a
comment
* or not.

* At the start, the CCOMMENTS var is loaded with a header line
identifying
* the program and showing the date of the comments extraction.

* As the top to bottom scan continues, comment (and blank) lines are
added
* to the CCOMMENTS variable, which will be written out as a comments
file
* when we're done.

* Since programs are stored as variable length ASCII records,
identifying
* lines is done by scanning for CRLF sequences within the program file.

* Instead of maintaining positioning within the program files, a simple
trick
* is used: the "occurances" parameter in the AT function. By simply
bumping
* this number, we can jump forward from line to line to continue the
scan
* without regard to knowing what offset we are within the file. Since
* we're only reading the top of each file, processing is fairly
efficient,
* regardless of the fact that using AT to scan for the "Nth" occurance
will
* more than likely restart VFP processing at the beginning of the file
* each time AT is used.

* After the 1st line of the prg is handled, subsequent scan restarts
will
* start at each of the successive CRLF markers in the file. For all
lines
* except the 1st, processing is handled by examining the text following
the
* CRLF to determine whether it's a comment or code line, and then
bumping the
* "occurances" variable so the restart begins with the next CRLF
sequence.

* This loop continues until EOF or a non-comment (code) line is
encountered.


cd (ccursrc) && switch into source folder
cprgvar = filetostr(ctheprg) && read prg into a var

nhits = 1 && new line occurance counter
ntotlen = len(cprgvar) && total len of prg text

ccomments = trim(ctheprg)+'
'+dtoc(datetime())+chr(13)+chr(10)+chr(13)+chr(10) && program name at
top, 2 CRLF's

do while .t. && loop till no more CRLF's

ncrlfpos = at(chr(13)+chr(10),cprgvar,nhits) && find first/next CR/LF
if empty(ncrlfpos) && if no CRLF at all
if nhits = 1 && and we're looking for 1st comment
line
ccomments = ccomments+cprgvar && take what we've got
endif && and exit
exit
endif


* If we get here, there are at least 2 lines in the prg

* Take the 1st line of the prg file, if it's a comment line, before we
* start taking successive lines (that is, when NHITS = 1, we're scanning
* for the 1st CRLF, which is a special case because we have yet to take
* the first comment line. After NHITS is incremented, we'll be
inspecting
* subsequent lines and taking comments from AFTER the CRLF (this works
because
* we'll then go back and find the next CRLF by bumping NHITS for the AT
scan)

if nhits = 1 && special process for 1st line only
if left(cprgvar,1) = '*'
ccomments = ccomments+left(cprgvar,ncrlfpos-1)+chr(13)+chr(10)
endif
endif

* Take blank lines and comment lines until we've got them all, then
we're done

* If another CRLF or a command, take it

if substr(cprgvar,ncrlfpos+2,2) = chr(13)+chr(10) .or. ;
substr(cprgvar,ncrlfpos+2,1) = '*'

remlen = ntotlen - ncrlfpos+2 && remaining prg len
if remlen > 200 && if more than a 200 chr line
left
remlen = 200 && limit scan for end of line to
200 chrs
endif

cnextline = substr(cprgvar,ncrlfpos+2,remlen) && take next 200 (or
less) chrs

* Find the next CRLF within the (200 or fewer chrs) extracted into
CNEXTLINE


nlinelen = at(chr(13)+chr(10),cnextline)


* If there is a CRLF, take text from the line up to the CRLF
* If there is no CRLF, take the entire line + add a CRLF


if empty(nlinelen) && if CRLF not found
ccomments = ccomments + trim(cnextline)+chr(13)+chr(10)
else
ccomments = ccomments + substr(cnextline,1,nlinelen+1)
endif

nhits = nhits + 1 && bump occurance # (next scan will start with
next occurance #)

else && else, no
exit && we're done
endif

enddo

* On return CCOMENTS will contain the extracted comments for this
program file

return
*
------------------------------------------------------------------------
procedure loadplist && load the CPRGLIST array with names of
* prgs in folder being scanned

dimension cprglist(500,5)

if right(trim(ccursrc),1) = '\'
ccursrc = alltrim(ccursrc)
else
ccursrc = alltrim(ccursrc)+'\'
endif

string = ccursrc+'*.prg' && all prgs in source folder
nprgcount =adir(cprglist,(string)) && load CPRGLIST array, get count
in NPRGCOUNT
if empty(nprgcount) && if empty
=messagebox("There are no .PRG files in "+trim(ccursrc),0,"Comment
grabber")
store .t. to ldoneflag && stop processing
endif

return
*
------------------------------------------------------------------------
procedure checkparms && check the input parameters
parameters csource,ctarget


* If the source prg library name wasn't passed or it's not a folder
name,
* prompt for it's name/loc

if vartype(csource) = 'U' .or. !directory(csource)
ccursrc = "c:\devtest"
ccursrc = getdir(ccursrc,"Source prgs")
else
ccursrc = csource
endif

* If the target folder name wasn't passed, create it in root folder with
* the name "C:\COMMENTS" (if C:\COMMENTS already exists, use it)

* If the target folder name was passed but it doesn't exist, create it.
Note
* that a folder structure will be created if parent/child folders are
named
* as the output folder name and none of the nodes exist.


if vartype(ctarget) = 'U' && if target folder name not supplied
ccurtgt = "c:\comments" && use default name c:\comments
else
ccurtgt = ctarget && use supplied target folder name
endif

if !directory(ccurtgt) && if target folder doesn't exist
md (ccurtgt) && create it now
endif

return




 
©2006 Bill Arnold
<-- Prior Message New Search Next Message -->