> 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



_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/profox
OT-free version of this list: http://leafe.com/mailman/listinfo/profoxtech
** All postings, unless explicitly stated otherwise, are the opinions of the 
author, and do not constitute legal or medical advice. This statement is added 
to the messages for those lawyers who are too stupid to see the obvious.

Reply via email to