home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
cppdoc.zip
/
cppdoc.cmd
next >
Wrap
OS/2 REXX Batch file
|
1997-01-06
|
45KB
|
1,216 lines
/* --------------------------------------------------------------------------
* $RCSfile: cppdoc.cmd,v $
* $Revision: 1.11 $
* $Date: 1997/01/06 15:07:16 $
* $Author: Bablok $
* --------------------------------------------------------------------------
* Synopsis:
*
* Documentation-Generator for C++ programs.
*
* cppdoc.cmd and cppdoc.htm are Copyright (c) 1996 by Bernhard Bablok
* --------------------------------------------------------------------------
* History:
*
* $Log: cppdoc.cmd,v $
* Revision 1.11 1997/01/06 15:07:16 Bablok
* added expandTabs-subroutine to replace tabs with blanks in input files
*
* Revision 1.10 1996/09/07 16:26:57 Bablok
* Various new features
* New commandline interface
*
* Revision 1.0 1996/06/06 14:25:36 Bablok
* Initial revision
*
* -------------------------------------------------------------------------- */
PARSE ARG cmdLine
CALL initConstants
CALL processArgs
CALL readIndex
DO numCycles
DO fileNr = GetOpt._optind TO GetOpt.0
CALL initVars GetOpt.fileNr
CALL readFiles
CALL findClasses
CALL findMember
CALL printDoc
END
END
CALL updateIndexFile
RETURN 0
/* -------------------------------------------------------------------------- */
/* some utility functions, for performance reasons at the head of the file */
/* -------------------------------------------------------------------------- */
/*----------------------------------------------------------------------------*/
/* expandTabs: Expand tabs to blanks */
/*----------------------------------------------------------------------------*/
expandTabs: PROCEDURE
tabInterval = 3
tabChar = D2C(9)
PARSE ARG string
tabPos = POS(tabChar,string)
DO WHILE tabPos > 0
tabOffset = tabPos//tabInterval
PARSE VALUE string WITH head (tabChar) tail
IF tabOffset = 0 THEN
string = head tail
ELSE
string = head || COPIES(' ',tabInterval+1-tabOffset) || tail
tabPos = POS(tabChar,string)
END
RETURN string
/* -------------------------------------------------------------------------- */
/* nextIdentifier: return position of next identifier and identifier */
/* of a given string */
/* -------------------------------------------------------------------------- */
nextIdentifier: PROCEDURE
PARSE ARG string, start
IF string = '' THEN
RETURN 0 ''
IF start = '' THEN
start = 1
IF start > LENGTH(string) THEN
RETURN 0 ''
string = SUBSTR(string,start)
first = VERIFY(string,'_abcdefghijklmnopqrstuvwxyz' ||,
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789','M')
IF first = 0 THEN
RETURN 0 ''
string = SUBSTR(string,first)
len = VERIFY(string,'_abcdefghijklmnopqrstuvwxyz' ||,
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') - 1
IF len = -1 THEN
len = LENGTH(string)
ident = SUBSTR(string,1,len)
IF ident = 'operator' & POS('(',string,len+1) > 2 THEN
ident = SPACE(SUBSTR(string,1,POS('(',string,len+1)-1),0)
RETURN start+first-1 ident
/* -------------------------------------------------------------------------- */
/* lastIdentifier: return last (c++)-identifier in a given string */
/* (including ~ for destructor, expecting no bitwise NOT) */
/* -------------------------------------------------------------------------- */
lastIdentifier: PROCEDURE
PARSE ARG string, start
IF string = '' THEN
RETURN ''
IF start = '' THEN
start = LENGTH(string)
revString = REVERSE(STRIP(SUBSTR(string,1,start)))
first = VERIFY(revString,'~_abcdefghijklmnopqrstuvwxyz' ||,
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789','M')
IF first = 0 THEN
RETURN ''
len = VERIFY(SUBSTR(revString,first),'~_abcdefghijklmnopqrstuvwxyz' ||,
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') - 1
IF len = -1 THEN
len = LENGTH(revString) - (first-1)
ident = REVERSE(SUBSTR(revString,first,len))
IF ident = 'operator' THEN DO
ident = STRIP(REVERSE(STRIP(SUBSTR(revString,1,len+first-1),'L','(')))
END /* IF ident = 'operator' THEN DO */
RETURN ident
/* -------------------------------------------------------------------------- */
/* findMatchingChar: find position of closing parenthesis, brace etc */
/* -------------------------------------------------------------------------- */
findMatchingChar: PROCEDURE
PARSE ARG string, start
cOpen = SUBSTR(string,start,1)
SELECT
WHEN cOpen = '(' THEN cClose = ')'
WHEN cOpen = '{' THEN cClose = '}'
WHEN cOpen = '[' THEN cClose = ']'
WHEN cOpen = '<' THEN cClose = '>'
WHEN cOpen = ')' THEN cClose = '('
WHEN cOpen = '}' THEN cClose = '{'
WHEN cOpen = ']' THEN cClose = '['
WHEN cOpen = '>' THEN cClose = '<'
OTHERWISE
RETURN 0
END /* SELECT */
IF POS(cOpen,')}]>') > 0 THEN DO
string = REVERSE(string)
start = LENGTH(string) - start + 1
END /* IF POS(cOpen,')}]>') > 0 THEN DO */
open = 1
next = 0
DO FOREVER
charPos = VERIFY(SUBSTR(string,start+next+1),cOpen||cClose,'M')
IF charPos = 0 THEN /* actually, this is an error */
RETURN 0
next = next + charPos
char = SUBSTR(string,start+next,1)
IF char = cOpen THEN
open = open + 1
ELSE
open = open - 1
IF open = 0 THEN DO
matchingPos = start + next
IF POS(cOpen,')}]>') > 0 THEN
matchingPos = LENGTH(string) - matchingPos + 1
RETURN matchingPos
END /* IF open = 0 THEN DO */
END /* DO FOREVER */
/* -------------------------------------------------------------------------- */
/* makeExternalRef: add anchor tag for external reference */
/* -------------------------------------------------------------------------- */
makeExternalRef: PROCEDURE EXPOSE externalRefs. className
PARSE ARG line
start = 1
CALL nextIdentifier line, start
PARSE VALUE RESULT WITH identPos ident
DO WHILE ident <> ''
IF externalRefs.ident <> '' & ident <> className THEN DO
ref = '<A HREF="'externalRefs.ident'">'ident'</A>'
head = SUBSTR(line,1,identPos-1)
tail = SUBSTR(line,identPos+LENGTH(ident))
line = head || ref || tail
identPos = identPos + LENGTH(externalRefs.ident) + 15
END /* IF externalRefs.ident <> '' & ident <> className THEN DO */
start = identPos + LENGTH(ident)
CALL nextIdentifier line, start
PARSE VALUE RESULT WITH identPos ident
END /* DO WHILE ident <> '' */
RETURN line
/* -------------------------------------------------------------------------- */
/* makeInternalRef: add anchor tag for internal reference */
/* -------------------------------------------------------------------------- */
makeInternalRef: PROCEDURE
PARSE ARG string, refToken, refAnchor
ref = '<A HREF="#'refAnchor'">'refToken'</A>'
PARSE VALUE string WITH head (refToken) tail
RETURN head || ref || tail
/* -------------------------------------------------------------------------- */
/* lastWord: return last word of given string */
/* -------------------------------------------------------------------------- */
lastWord: PROCEDURE
PARSE ARG string
RETURN WORD(string,WORDS(string))
/* -------------------------------------------------------------------------- */
/* count: Return count of a given character in a given string */
/* -------------------------------------------------------------------------- */
count: PROCEDURE
PARSE ARG c, string
start = 1
num = 0
DO FOREVER
col = POS(c,string,start)
IF col > 0 THEN DO
num = num + 1
start = col + 1
END /* IF col > 0 THEN DO */
ELSE
RETURN num
END /* DO FOREVER */
/* -------------------------------------------------------------------------- */
/* changestr: Change multiple occurences of a given string */
/* -------------------------------------------------------------------------- */
changestr: PROCEDURE
PARSE ARG string, tableo, tablei, start, delim, once
IF start = '' THEN
start = 1
IF delim = '' THEN
delim = ' '
IF once = '' THEN
once = 0
DO FOREVER
IF tablei = '' THEN
LEAVE
PARSE VALUE tablei WITH oldToken (delim) tablei
PARSE VALUE tableo WITH newToken (delim) tableo
DO FOREVER
IF POS(oldToken,string,start) = 0 THEN
LEAVE
PARSE VALUE SUBSTR(string,start) WITH head (oldToken) rest
IF start > 1 THEN
string = SUBSTR(string,1,start-1) || head || newToken || rest
ELSE
string = head || newToken || rest
IF once THEN
LEAVE
END /* DO FOREVER */
END /* DO FOREVER */
RETURN string
/* -------------------------------------------------------------------------- */
/* initConstants: Define constants */
/* -------------------------------------------------------------------------- */
initConstants:
MSG_READ_FILES = "Reading files ..."
MSG_READ_INDEX = "Reading index"
MSG_FIND_CLASSES = "Looking for class declarations"
MSG_FIND_MEMBER = "Looking for member definitions"
MSG_PRINT_DOC = "Generating documentation..."
MSG_PRINT_DESC = "... class description"
MSG_PRINT_INHER = "... class inheritance"
MSG_CLASS_INTERFACE = "... class interface"
MSG_MEMBER_DOC = "... member description"
ERR_TARGET_DIR = "Error: Target directory does not exist"
ERR_FILE_NOT_FOUND = "Error: File" fileName "not found"
ERR_NO_FILES = "Error: No files"
ERR_INVALID_INDEX = "Error: Index-file" indexFile "is invalid"
ERR_UNBALANCED_BRACES = "Error: Missing '}'"
DOC_TITLE = 'Class Documentation for C++-Class: '
SOURCE_H2 = 'Source'
CLASS_INH_H2 = 'Inheritance'
CLASS_DOC_H2 = 'Class Description'
CLASS_DOC_NONE = 'No description available.'
CLASS_INT_H2 = 'Class Interface'
CLASS_INT_REF = 'Return to class interface.'
CLASS_INT_NONE = 'Class declaration not found.'
MEMBER_DOC_H2 = 'Description of Functions (Members and Others)'
MEMBER_DOC_NONE = 'No details about members available.'
INDEX_TITLE = 'Index to C++-Class Documentation'
INDEX_H1 = 'Index'
CPP_EXTENSIONS = 'cpp cc cxx c'
NLS_CHAR_ESC = 'ä ö ü Ä Ö Ü ß'
NLS_CHAR = 'ä ö ü Ä Ö Ü ß'
MAX_LINE_LENGTH = 70
CALL RxFuncAdd 'SysFileDelete', 'RexxUtil', 'SysFileDelete'
CALL RxFuncAdd 'SysFileTree', 'RexxUtil', 'SysFileTree'
RETURN
/* -------------------------------------------------------------------------- */
/* processArgs: process command line arguments, setup variables */
/* -------------------------------------------------------------------------- */
processArgs:
CALL setupArg cmdLine
GetOpt._opterr = 0
printAll = 1
printSource = 0
printDesc = 0
printInter = 0
printMem = 0
omitTrailer = 0
numCycles = 1
relativeLinks = 0
targetDirectory = '.'
indexFile = ''
hidePrivateSections = 0
optstr = 'x:t:r2Hsdimo'
DO UNTIL c = -1 | c = '?'
c = GetOpt(optstr)
SELECT
WHEN c = 'x' THEN
indexFile = GetOpt._optarg
WHEN c = 't' THEN
targetDirectory = STRIP(GetOpt._optarg,'T','\')
WHEN c = 'r' THEN
relativeLinks = 1
WHEN c = '2' THEN
numCycles = 2
WHEN c = 'H' THEN
hidePrivateSections = 1
WHEN c = 's' THEN DO
printAll = 0
printSource = 1
END
WHEN c = 'd' THEN DO
printAll = 0
printDesc = 1
END
WHEN c = 'i' THEN DO
printAll = 0
printInter = 1
END
WHEN c = 'm' THEN DO
printAll = 0
printMem = 1
END
WHEN c = 'o' THEN
omitTrailer = 1
WHEN c = '?' THEN
CALL usage
OTHERWISE
NOP
END
END
IF printAll THEN DO
printSource = 1
printDesc = 1
printInter = 1
printMem = 1
END
curDir = DIRECTORY()
targetDirectory = DIRECTORY(targetDirectory)
CALL DIRECTORY curDir
IF targetDirectory = '' THEN DO
SAY ERR_TARGET_DIR
EXIT 3
END
ELSE
targetDirectory = targetDirectory'\'
IF indexFile <> '' THEN
indexFile = targetDirectory || indexFile
/* process filename arguments --------------------------------------------- */
i = GetOpt._optind
DO WHILE i <= GetOpt.0
IF POS('*',GetOpt.i) > 0 | POS('?',GetOpt.i) > 0 THEN DO
CALL SysFileTree GetOpt.i,'files.','FO'
DO j = i+1 TO GetOpt.0
k = j - 1
GetOpt.k = GetOpt.j
END
DO j = 1 TO files.0
k = GetOpt.0 - 1 + j
GetOpt.k = files.j
END
GetOpt.0 = GetOpt.0 + files.0 - 1
END
ELSE
i = i + 1
END
IF GetOpt._optind > GetOpt.0 THEN DO
SAY ERR_NO_FILES
CALL usage
END
RETURN
/* -------------------------------------------------------------------------- */
/* initVars: Initialize Variables */
/* -------------------------------------------------------------------------- */
initVars:
PARSE ARG fileName
fileName = STREAM(fileName,'C','query exists')
IF fileName = '' THEN DO
SAY ERR_FILE_NOT_FOUND
EXIT 3
END /* IF fileName = '' THEN DO */
sourceFiles = '<A HREF="file:///'fileName'">'fileName'</A>'
classList = ''
classDocu. = ''
classInterf. = ''
classInherit. = ''
classBase. = ''
classMember. = ''
memberDef. = ''
memberDocu. = ''
RETURN 0
/* -------------------------------------------------------------------------- */
/* readFiles: Read interface and implementation files */
/* -------------------------------------------------------------------------- */
readFiles:
SAY MSG_READ_FILES
i = 0
SAY '...' fileName
DO WHILE LINES(fileName) > 0
i = i + 1
line.i = STRIP(expandTabs(LINEIN(fileName)),'T')
IF line.i = '' THEN DO
i = i - 1
ITERATE
END /* IF line.i = '' THEN DO */
ELSE IF WORD(line.i,1) = '#define' THEN DO
DO UNTIL RIGHT(line.i,1) <> '\'
line.i = STRIP(expandTabs(LINEIN(fileName)),'T')
END /* DO UNTIL RIGHT(line.i,1) <> '\' */
i = i - 1
ITERATE
END
ELSE IF LEFT(STRIP(line.i),4) = '//@p' THEN DO
IF hidePrivateSections THEN DO
i = i - 1
ITERATE
END
ELSE DO
ppos = POS('//@p',line.i) + 3
line.i = OVERLAY(' ',line.i,ppos)
END
END
END /* DO WHILE LINES(fileName) > 0 */
CALL LINEOUT fileName
DO j = 1 TO WORDS(CPP_EXTENSIONS)
impFile = SUBSTR(fileName,1,LASTPOS('.',fileName)) || WORD(CPP_EXTENSIONS,j)
impFile = STREAM(impFile,'C','query exists')
IF impFile <> '' THEN DO
SAY '...' impFile
sourceFiles = sourceFiles',' '<A HREF="file:///'impFile'">'impFile'</A>'
DO WHILE LINES(impFile) > 0
i = i + 1
line.i = STRIP(expandTabs(LINEIN(impFile)))
IF line.i = '' THEN DO
i = i - 1
ITERATE
END /* IF line.i = '' THEN DO */
ELSE IF WORD(line.i,1) = '#define' THEN DO
DO UNTIL RIGHT(line.i,1) <> '\'
line.i = STRIP(expandTabs(LINEIN(impFile)),'T')
END /* DO UNTIL RIGHT(line.i,1) <> '\' */
i = i - 1
ITERATE
END /* DO UNTIL RIGHT(line.i,1) <> '\' */
ELSE IF LEFT(line.i,4) = '//@p' THEN DO
IF hidePrivateSections THEN DO
i = i - 1
ITERATE
END
ELSE DO
ppos = POS('//@p',line.i) + 3
line.i = OVERLAY(' ',line.i,ppos)
END
END
END /* DO WHILE LINES(impFile) > 0 */
CALL LINEOUT impFile
LEAVE
END /* IF impFile <> '' THEN DO */
END /* DO j = 1 TO WORDS(CPP_EXTENSIONS) */
line.0 = i
lastLine = line.0 /* default value, in case file does not contain class def */
RETURN
/* -------------------------------------------------------------------------- */
/* readIndex: Read index file */
/* -------------------------------------------------------------------------- */
readIndex:
indexAddBefore = 0
externalRefsClassList = ''
externalRefs. = ''
classIndexInfo. = ''
IF indexFile <> '' THEN DO
IF POS('.',indexFile,LASTPOS('\',indexFile)+1) = 0 THEN
indexFile = STRIP(indexFile)'.htm'
IF STREAM(indexFile,'C','query exists') <> '' THEN DO
i = 0
SAY MSG_READ_INDEX indexFile
DO WHILE LINES(indexFile)
i = i + 1
index.i = expandTabs(LINEIN(indexFile))
index.i._class = '---'
IF LEFT(STRIP(index.i),4) = '<LI>' THEN DO
PARSE VALUE index.i WITH . '"' classNameFile '">' className '<' .
index.i._class = className
externalRefs.className = classNameFile
END /* IF LEFT(STRIP(index.i),4) = '<LI>' THEN DO */
ELSE IF LEFT(STRIP(index.i),5) = '</UL>' THEN
indexAddBefore = i
END /* DO WHILE LINES(indexFile) */
CALL LINEOUT indexFile
index.0 = i
IF indexAddBefore = 0 THEN DO
SAY ERR_INVALID_INDEX
EXIT 3
END /* IF indexAddBefore = 0 THEN DO */
END /* IF STREAM(indexFile,'C','query exists') <> '' THEN DO */
END /* IF indexFile <> '' THEN DO */
RETURN
/* -------------------------------------------------------------------------- */
/* findClasses: find class declarations */
/* -------------------------------------------------------------------------- */
findClasses:
SAY MSG_FIND_CLASSES
comment = 0
DO i = 1 TO line.0
/* skip comment lines --------------------------------------------------- */
IF LEFT(STRIP(line.i),2) = '//' THEN
ITERATE
ELSE IF comment & POS('*/',line.i) = 0 THEN
ITERATE
ELSE IF comment THEN DO
comment = 0
ITERATE
END /* ELSE IF comment THEN DO */
ELSE IF POS('/*',line.i) > 0 & POS('*/',line.i) = 0 THEN DO
comment = 1
ITERATE
END /* ELSE IF POS('/*',line.i) > 0 & POS('*/',line.i) = 0 THEN DO */
ELSE IF POS('/*',line.i) > 0 THEN
ITERATE
/* check if class token is present -------------------------------------- */
IF POS('class',line.i) > 0 THEN DO
/* concatenate lines until end of statement or beginning of declaration */
line = line.i
n = i - 1
DO WHILE i < line.0 & POS(';',line) = 0 & POS('{',line) = 0
i = i + 1
line = line line.i
END /* DO WHILE i < line.0 & POS(';',line) = 0 & POS('{',line) = 0 */
/* omit template definitions of functions ----------------------------- */
IF WORDPOS('template',line) > 0 THEN DO
lt = POS('<',line)
IF WORDPOS('class',SUBSTR(line,findMatchingChar(line,lt))) = 0 THEN
ITERATE
END /* IF WORDPOS('template',line) > 0 THEN DO */
/* omit forward declarations ------------------------------------------ */
IF POS('{',line) > 0 THEN DO /* found a class declaration */
IF POS(':',line) = 0 THEN DO /* no classes inherited from */
PARSE VALUE line WITH this '{' .
className = lastWord(this)
classInherit.className = this
END /* IF POS(':',line) = 0 THEN DO */
ELSE DO
PARSE VALUE line WITH this ':' base '{' .
className = lastWord(this)
classInherit.className = this ':' base
END /* ELSE DO */
classList = classList className
IF WORDPOS(className,externalRefsClassList) = 0 THEN
externalRefsClassList = externalRefsClassList className
IF relativeLinks THEN
externalRefs.className = className'.htm'
ELSE
externalRefs.className = 'file:///'targetDirectory||className'.htm'
CALL findClassDocu className, n
CALL findClassInterface className, line
END /* IF POS('{',line) > 0 THEN DO */
END /* IF POS('class',line.i) > 0 THEN DO */
END /* DO i = 1 TO line.0 */
RETURN
/* -------------------------------------------------------------------------- */
/* findClassDocu: extract class documentation */
/* -------------------------------------------------------------------------- */
findClassDocu: PROCEDURE EXPOSE line. classDocu. classIndexInfo.
PARSE ARG className, n
DO i = n TO 1 BY -1 UNTIL LEFT(STRIP(line.i),3) = '//@'
END /* DO i = n TO 1 BY -1 UNTIL LEFT(STRIP(line.i),3) = '//@' */
IF i > 0 THEN DO
j = 0
DO WHILE i > 0 & LEFT(STRIP(line.i),3) = '//@'
j = j + 1
classDocu.className.j = STRIP(SUBSTR(STRIP(line.i),4))
i = i - 1
END /* DO WHILE i > 0 & LEFT(STRIP(line.i),3) = '//@' */
classIndexInfo.className = classDocu.className.j
classDocu.className.0 = j - 1
END /* IF i > 0 THEN DO */
ELSE
classDocu.className.0 = 0
RETURN
/* -------------------------------------------------------------------------- */
/* findClassInterface: extract class interface */
/* -------------------------------------------------------------------------- */
findClassInterface: PROCEDURE EXPOSE line. classInterf. i lastLine
PARSE ARG className, line
line.i = STRIP(SUBSTR(line' ',POS('{',line)+1))
IF line.i = '' THEN
i = i + 1
open = 1
j = 0
DO i = i TO line.0
open = open + count('{',line.i) - count('}',line.i)
IF open < 0 THEN DO
SAY ERR_UNBALANCED_BRACES
EXIT 3
END /* IF open < 0 THEN DO */
ELSE IF open = 0 THEN DO
endPos = LASTPOS('}',line.i) /* ELSE IF open = 0 THEN DO */
line = STRIP(SUBSTR(line.i,1,endPos-1))
IF line <> '' THEN DO
j = j + 1
classInterf.className.j = line
END /* IF line <> '' THEN DO */
LEAVE i
END /* ELSE IF open = 0 THEN DO */
ELSE DO
j = j + 1
classInterf.className.j = line.i
END /* ELSE DO */
END /* DO i = i TO line.0 */
lastLine = i
classInterf.className.0 = j
RETURN
/* -------------------------------------------------------------------------- */
/* findMember: locate member definition */
/* -------------------------------------------------------------------------- */
findMember:
SAY MSG_FIND_MEMBER
DO i = lastLine + 1 TO line.0
/* skip lines before next docu-block ------------------------------------ */
DO WHILE i <= line.0 & LEFT(STRIP(line.i),3) <> '//@'
i = i + 1
ITERATE
END /* DO WHILE i <= line.0 & LEFT(STRIP(line.i),3) <> '//@' */
/* read docu-block ------------------------------------------------------ */
IF i <= line.0 & LEFT(STRIP(line.i),3) = '//@' THEN DO
j = 0
DO WHILE i <= line.0 & LEFT(STRIP(line.i),3) = '//@'
j = j + 1
doc.j = STRIP(SUBSTR(STRIP(line.i),4))
i = i + 1
END /* DO WHILE i <= line.0 & LEFT(STRIP(line.i),3) = '//@' */
doc.0 = j
END /* IF i <= line.0 & LEFT(STRIP(line.i),3) = '//@' THEN DO */
/* read member definition ----------------------------------------------- */
IF i <= line.0 THEN DO
line = STRIP(line.i)
line = changestr(line,'°°','::')
DO WHILE i <= line.0 & POS('{',line) = 0 & POS(':',line) = 0
i = i + 1
line = line STRIP(line.i)
line = changestr(line,'°°','::')
END /* DO WHILE i <= line.0 & POS('{',line) = 0 & POS(':',line) = 0 */
IF POS(':',line) > 0 THEN
line = STRIP(SUBSTR(line,1,POS(':',line)-1)) /* this is a constructor! */
ELSE
line = STRIP(SUBSTR(line,1,POS('{',line)-1))
line = changestr(line,'::','°°')
/* try to find a function/member definition --------------------------- */
start = findMatchingChar(line,LASTPOS(')',line))-1
memberName = SPACE(lastIdentifier(line,start),0)
start = start - LENGTH(memberName) -,
POS(REVERSE(memberName),REVERSE(SUBSTR(line,1,start))) + 1
IF RIGHT(STRIP(SUBSTR(line,1,start)),2) = '::' THEN DO /* a member! */
col = LASTPOS('::',line,start)
DO WHILE col > 0
IF RIGHT(STRIP(SUBSTR(line,1,col-1)),1) = '>' THEN /* a template */
col = findMatchingChar(line,LASTPOS('>',line,col-1))
ident = lastIdentifier(line,col-1)
IF WORDPOS(ident,classList) > 0 THEN DO
className = ident
LEAVE
END /* IF WORDPOS(ident,classList) > 0 THEN DO */
ELSE
col = LASTPOS('::',line,col-1)
END /* DO WHILE col > 0 */
END /* IF RIGHT(STRIP(SUBSTR(line,1,start)),2) = '::' THEN DO */
memberName = changestr(memberName,'°amp; < >','& < >')
memberName = changestr(memberName,'&','°')
IF WORDPOS(memberName,classMember.className) > 0 THEN
memberName = memberName'!'i /* overloaded! */
classMember.className = classMember.className memberName
DO j=1 TO doc.0
memberDocu.className.memberName.j = doc.j
END /* DO j=1 TO doc.0 */
memberDocu.className.memberName.0 = doc.0
memberDef.className.memberName = line
END /* IF i <= line.0 THEN DO */
END /* DO i = lastLine + 1 TO line.0 */
RETURN
/* -------------------------------------------------------------------------- */
/* printDoc: generate HTML-file */
/* -------------------------------------------------------------------------- */
printDoc:
DO i = 1 TO WORDS(classList)
className = WORD(classList,i)
docFile = targetDirectory||className'.htm'
SAY MSG_PRINT_DOC className '...'
CALL SysFileDelete docFile
CALL printHeader
IF printSource THEN
CALL LINEOUT docFile, '<H2>'SOURCE_H2'</H2><P>'sourceFiles'<P><HR>'
IF printDesc THEN
CALL printClassDoc
IF printInter THEN DO
CALL printClassInheritance
CALL printClassInterface
END
IF printMem THEN
CALL printMemberDoc
CALL printTrailer docFile
CALL LINEOUT docFile
END /* DO i = 1 TO WORDS(classList) */
RETURN
/* -------------------------------------------------------------------------- */
/* printHeader: header for HTML-file, including source and inheritance */
/* -------------------------------------------------------------------------- */
printHeader:
CALL LINEOUT docFile, '<!-- Class documentation generated by CPPDOC -->'
CALL LINEOUT docFile, '<HTML>'
CALL LINEOUT docFile, '<HEAD>'
CALL LINEOUT docFile, '<TITLE>'DOC_TITLE className'</TITLE>'
CALL LINEOUT docFile, '</HEAD>'
CALL LINEOUT docFile, '<BODY>'
CALL LINEOUT docFile, '<H1>Class' className'</H1>'
RETURN
/* -------------------------------------------------------------------------- */
/* printClassInheritance: Class inheritance */
/* -------------------------------------------------------------------------- */
printClassInheritance:
SAY MSG_PRINT_INHER
CALL LINEOUT docFile, '<H2>'CLASS_INH_H2'</H2>'
indent = 0
CALL LINEOUT docFile, '<P><PRE>'
def = classInherit.className
DO WHILE LENGTH(def) > MAX_LINE_LENGTH
splitPos = LASTPOS(',',def,MAX_LINE_LENGTH)
IF splitPos = 0 THEN
splitPos = LASTPOS(' ',def,MAX_LINE_LENGTH)
token = changestr(SUBSTR(def,1,splitPos),'°amp; < >','& < >')
token = changestr(token,'&','°')
def = STRIP(SUBSTR(def,splitPos+1))
CALL LINEOUT docFile, COPIES(' ',indent) makeExternalRef(token)
indent = 5
END /* DO WHILE LENGTH(def) > MAX_LINE_LENGTH */
def = changestr(def,'°amp; < >','& < >')
def = changestr(def,'&','°')
CALL LINEOUT docFile, COPIES(' ',indent) makeExternalRef(def)
CALL LINEOUT docFile, '</PRE></P>'
CALL LINEOUT docFile, '<HR>'
RETURN
/* -------------------------------------------------------------------------- */
/* printClassDoc: class description */
/* -------------------------------------------------------------------------- */
printClassDoc:
SAY MSG_PRINT_DESC
CALL LINEOUT docFile, '<H2>'CLASS_DOC_H2'</H2><P>'
IF classDocu.className.0 = 0 THEN
CALL LINEOUT docFile, CLASS_DOC_NONE
ELSE
DO j = classDocu.className.0 TO 1 BY -1
CALL LINEOUT docFile,,
changestr(classDocu.className.j,NLS_CHAR_ESC,NLS_CHAR)
END /* DO j = classDocu.className.0 TO 1 BY -1 */
CALL LINEOUT docFile, '</P><HR>'
RETURN
/* -------------------------------------------------------------------------- */
/* printClassInterface: class interface */
/* -------------------------------------------------------------------------- */
printClassInterface:
SAY MSG_CLASS_INTERFACE
CALL LINEOUT docFile, '<H2><A NAME="'CLASS_INT_H2'">'CLASS_INT_H2'</A></H2><P>'
IF classInterf.className.0 = 0 THEN
CALL LINEOUT docFile, CLASS_INT_NONE
ELSE DO
CALL LINEOUT docFile, '<PRE>'
doneInternalLinks = ''
comment = 0
DO j=1 TO classInterf.className.0
line = classInterf.className.j
/* skip comment lines ----------------------------------------------- */
IF LEFT(STRIP(line),2) = '//' THEN DO
line = changestr(line,'°amp; < >','& < >')
line = changestr(line,'&','°')
CALL LINEOUT docFile, changestr(line,NLS_CHAR_ESC,NLS_CHAR)
ITERATE
END /* IF LEFT(STRIP(line),2) = '//' THEN DO */
ELSE IF comment & POS('*/',line) = 0 THEN DO
line = changestr(line,'°amp; < >','& < >')
line = changestr(line,'&','°')
CALL LINEOUT docFile, changestr(line,NLS_CHAR_ESC,NLS_CHAR)
ITERATE
END
ELSE IF comment THEN DO
comment = 0
line = changestr(line,'°amp; < >','& < >')
line = changestr(line,'&','°')
CALL LINEOUT docFile, changestr(line,NLS_CHAR_ESC,NLS_CHAR)
ITERATE
END /* ELSE IF comment THEN DO */
ELSE IF POS('/*',line) > 0 & POS('*/',line) = 0 THEN DO
comment = 1
line = changestr(line,'°amp; < >','& < >')
line = changestr(line,'&','°')
CALL LINEOUT docFile, changestr(line,NLS_CHAR_ESC,NLS_CHAR)
ITERATE
END /* ELSE IF POS('/*',line) > 0 & POS('*/',line) = 0 THEN DO */
ELSE IF POS('/*',line) > 0 THEN DO
line = changestr(line,'°amp; < >','& < >')
line = changestr(line,'&','°')
CALL LINEOUT docFile, changestr(line,NLS_CHAR_ESC,NLS_CHAR)
ITERATE
END
/* print keywords private:, protected: and public: in bold ------------ */
IF WORDPOS('private:',line) > 0 THEN DO
CALL LINEOUT docFile, '</PRE>'
CALL LINEOUT docFile, changestr(line,'<B>private:</B>','private:',,,1)
CALL LINEOUT docFile, '<PRE>'
ITERATE
END /* IF WORDPOS('private:',line) > 0 THEN DO */
IF WORDPOS('protected:',line) > 0 THEN DO
CALL LINEOUT docFile, '</PRE>'
CALL LINEOUT docFile,,
changestr(line,'<B>protected:</B>','protected:',,,1)
CALL LINEOUT docFile, '<PRE>'
ITERATE
END /* IF WORDPOS('protected:',line) > 0 THEN DO */
IF WORDPOS('public:',line) > 0 THEN DO
CALL LINEOUT docFile, '</PRE>'
CALL LINEOUT docFile, changestr(line,'<B>public:</B>','public:',,,1)
CALL LINEOUT docFile, '<PRE>'
ITERATE
END /* IF WORDPOS('public:',line) > 0 THEN DO */
/* check for internal links ------------------------------------------- */
IF POS('(',line) > 0 THEN DO
ident = lastIdentifier(line,POS('(',line))
line = changestr(line,'°amp; < >','& < >')
line = changestr(line,'&','°')
ident = changestr(ident,'°amp; < >','& < >')
ident = changestr(ident,'&','°')
IF WORDPOS(SPACE(ident,0),classMember.className) > 0 THEN
DO k = WORDPOS(SPACE(ident,0),classMember.className) TO,
WORDS(classMember.className)
member = WORD(classMember.className,k)
IF ABBREV(member,SPACE(ident,0)) &,
WORDPOS(member,doneInternalLinks) = 0 THEN DO
line = makeInternalRef(line,ident,member)
doneInternalLinks = doneInternalLinks member
LEAVE
END /* WORDPOS(member,doneInternalLinks) = 0 THEN DO */
END /* DO k = WORDPOS(SPACE(ident,0),classMember.className) TO, */
END /* IF POS('(',line) > 0 THEN DO */
ELSE DO
line = changestr(line,'°amp; < >','& < >')
line = changestr(line,'&','°')
END /* ELSE DO */
line = makeExternalRef(changestr(line,NLS_CHAR_ESC,NLS_CHAR))
CALL LINEOUT docFile, line
END /* DO j=1 TO classInterf.className.0 */
CALL LINEOUT docFile, '</PRE>'
END /* ELSE DO */
CALL LINEOUT docFile, '</P><HR>'
RETURN
/* -------------------------------------------------------------------------- */
/* printMemberDoc: member description */
/* -------------------------------------------------------------------------- */
printMemberDoc:
SAY MSG_MEMBER_DOC
CALL LINEOUT docFile, '<H2>'MEMBER_DOC_H2'</H2><P>'
IF WORDS(classMember.className) = 0 THEN
CALL LINEOUT docFile, MEMBER_DOC_NONE '</P><HR>'
ELSE
DO j=1 TO WORDS(classMember.className)
memberName = WORD(classMember.className,j)
PARSE VALUE memberName WITH memberTitle_H3 '!' .
CALL LINEOUT docFile, '<H3><A NAME="'memberName'">'memberTitle_H3 ||,
'</A></H3><P>'
/* member definition ---------------------------------------------------- */
indent = 0
CALL LINEOUT docFile, '<PRE>'
def = memberDef.className.memberName
DO WHILE LENGTH(def) > MAX_LINE_LENGTH
splitPos = LASTPOS(',',def,MAX_LINE_LENGTH)
IF splitPos = 0 THEN
splitPos = LASTPOS(' ',def,MAX_LINE_LENGTH)
token = changestr(SUBSTR(def,1,splitPos),'°amp; < >','& < >')
token = changestr(token,'&','°')
def = STRIP(SUBSTR(def,splitPos+1))
CALL LINEOUT docFile, COPIES(' ',indent) makeExternalRef(token)
indent = 5
END /* DO WHILE LENGTH(def) > MAX_LINE_LENGTH */
def = changestr(def,'°amp; < >','& < >')
def = changestr(def,'&','°')
CALL LINEOUT docFile, COPIES(' ',indent) makeExternalRef(def)
CALL LINEOUT docFile, '</PRE></P><P>'
/* member description ------------------------------------------------- */
DO k=1 TO memberDocu.className.memberName.0
CALL LINEOUT docFile,,
changestr(memberDocu.className.memberName.k,NLS_CHAR_ESC,NLS_CHAR)
END /* DO k=1 TO memberDocu.className.memberName.0 */
CALL LINEOUT docFile, '</P><P><A HREF="#'CLASS_INT_H2'">' ||,
CLASS_INT_REF'</A></P><HR>'
END /* DO j=1 TO WORDS(classMember.className) */
RETURN
/* -------------------------------------------------------------------------- */
/* printTrailer: trailer for HTML-file */
/* -------------------------------------------------------------------------- */
printTrailer:
ARG targetFile
IF omitTrailer THEN DO
CALL LINEOUT targetFile, '<P>CPPDOC - (C) by Bernhard Bablok, 1996</P>'
CALL LINEOUT targetFile, '<P>Please send comments, suggestions, bug-reports to:'
CALL LINEOUT targetFile, '<A HREF="mailto:ua302cb@sunmail.lrz-muenchen.de">' ||,
'Bernhard Bablok</A></P>'
END
CALL LINEOUT targetFile, '</BODY>'
CALL LINEOUT targetFile, '</HTML>'
RETURN
/* -------------------------------------------------------------------------- */
/* updateIndexFile: add index entries */
/* -------------------------------------------------------------------------- */
updateIndexFile:
IF indexFile = '' THEN
RETURN
IF STREAM(indexFile,'C','query exists') = '' THEN DO
CALL LINEOUT indexFile, '<!-- Class index generated by CPPDOC -->'
CALL LINEOUT indexFile, '<HTML>'
CALL LINEOUT indexFile, '<HEAD>'
CALL LINEOUT indexFile, '<TITLE>'INDEX_TITLE'</TITLE>'
CALL LINEOUT indexFile, '</HEAD>'
CALL LINEOUT indexFile, '<BODY>'
CALL LINEOUT indexFile, '<H1>'INDEX_H1'</H1><P><UL>'
DO i=1 TO WORDS(externalRefsClassList)
className = WORD(externalRefsClassList,i)
CALL LINEOUT indexFile, '<LI><A HREF="'externalRefs.className ||,
'">'className'</A>',
changestr(classIndexInfo.className,NLS_CHAR_ESC,NLS_CHAR)
END
CALL LINEOUT indexFile, '</UL></P><HR>'
CALL printTrailer indexFile
CALL LINEOUT indexFile
END /* IF STREAM(indexFile,'C','query exists') = '' THEN DO */
ELSE DO
CALL SysFileDelete indexFile
DO i=1 TO indexAddBefore - 1
IF WORDPOS(index.i._class,externalRefsClassList) = 0 THEN
CALL LINEOUT indexFile, index.i
END /* DO i=1 TO indexAddBefore - 1 */
DO i=1 TO WORDS(externalRefsClassList)
className = WORD(externalRefsClassList,i)
CALL LINEOUT indexFile, '<LI><A HREF="'externalRefs.className ||,
'">'className'</A>',
changestr(classIndexInfo.className,NLS_CHAR_ESC,NLS_CHAR)
END
DO i=indexAddBefore TO index.0
IF WORDPOS(index.i._class,externalRefsClassList) = 0 THEN
CALL LINEOUT indexFile, index.i
END /* DO i=indexAddBefore TO index.0 */
CALL LINEOUT indexFile
END /* ELSE DO */
RETURN
/* -------------------------------------------------------------------------- */
/* usage: usage information */
/* -------------------------------------------------------------------------- */
usage:
SAY
SAY 'CPPDOC 1.11, (c) by Bernhard Bablok, 1996-1997'
SAY
SAY 'Usage: cppdoc [-x indexFile] [-t targetDirectory] [-rH2sdim] file [file ...]'
SAY
SAY 'Options: -r use relative links'
SAY ' -H hide private sections (sections with tag //@p)'
SAY ' -2 process twice'
SAY ' -s print source reference -|'
SAY ' -d print class description |- default: print all'
SAY ' -i print class interface |'
SAY ' -m print member description -|'
EXIT 1
/*-------------------------------------------------------------------------
GetOpt - parse options from REXX program command line
Copyright (c) 1994 Lawrence R Buchanan. ALL RIGHTS RESERVED.
-------------------------------------------------------------------------*/
GetOpt: PROCEDURE EXPOSE GetOpt.
PARSE ARG optstr
i = GetOpt._optind
IF GetOpt._sp = 1 THEN DO
IF GetOpt._optind > GetOpt.0 | ,
SUBSTR(GetOpt.i, 1, 1, '00'x) <> '-' | ,
SUBSTR(GetOpt.i, 2, 1, '00'x) = '00'x THEN
RETURN -1
ELSE
IF GetOpt.i = '--' THEN DO
GetOpt._optind = GetOpt._optind + 1
RETURN -1
END
END
c = SUBSTR(GetOpt.i, GetOpt._sp+1, 1, '00'x)
GetOpt._optopt = c
cp = POS(c, optstr)
IF c = ':' | cp = 0 THEN DO
IF GetOpt._opterr = 1 THEN
SAY GetOpt._program ': illegal option --' c
GetOpt._sp = GetOpt._sp + 1
IF SUBSTR(GetOpt.i, GetOpt._sp+1, 1, '00'x) = '00'x THEN DO
GetOpt._optind = GetOpt._optind + 1
GetOpt._sp = 1
END
RETURN '?'
END
cp = cp + 1
IF SUBSTR(optstr, cp, 1, '00'x) = ':' THEN DO
IF SUBSTR(GetOpt.i, GetOpt._sp+2, 1, '00'x) <> '00'x THEN DO
GetOpt._optarg = SUBSTR(GetOpt.i, GetOpt._sp+2)
GetOpt._optind = GetOpt._optind + 1
END
ELSE DO
GetOpt._optind = GetOpt._optind + 1
i = GetOpt._optind
IF GetOpt._optind > GetOpt.0 THEN DO
IF GetOpt._opterr = 1 THEN
SAY GetOpt._program ': option requires an argument --' c
GetOpt._sp = 1
RETURN '?'
END
ELSE DO
GetOpt._optarg = GetOpt.i
GetOpt._optind = GetOpt._optind + 1
END
END
GetOpt._sp = 1
END
ELSE DO
GetOpt._sp = GetOpt._sp + 1
IF SUBSTR(GetOpt.i, GetOpt._sp+1, 1, '00'x) = '00'x THEN DO
GetOpt._sp = 1
GetOpt._optind = GetOpt._optind + 1
END
GetOpt._optarg = ''
END
RETURN c
/* End of GetOpt */
/*-------------------------------------------------------------------------
SetupArg - Parse command-line arguments and store in stem GetOpt.
Copyright (c) 1994 Lawrence R Buchanan. ALL RIGHTS RESERVED.
-------------------------------------------------------------------------*/
SetupArg: PROCEDURE EXPOSE GetOpt.
PARSE ARG arglist
/* Initialize variables used in GetOpt subroutine. */
GetOpt. = ''
GetOpt._opterr = 1
GetOpt._optind = 1
GetOpt._sp = 1
/* Place program name in GetOpt._program. */
PARSE SOURCE os . GetOpt._program .
IF os = 'OS/2' THEN DO
GetOpt._program = FILESPEC('N', GetOpt._program)
GetOpt._program = DELSTR(GetOpt._program, LASTPOS('.', GetOpt._program))
END
/* Make sure the command-line contains an even number of
quotation characters. If it doesn't, I can't continue. */
IF count('"',arglist) // 2 THEN DO
SAY GetOpt._program ': Unbalanced quotation marks in command-line'
EXIT 255
END
i = 0
/* Load command-line options into GetOpt.1 through GetOpt.n. */
DO WHILE arglist <> ''
i = i + 1
PARSE VAR arglist GetOpt.i arglist
/* If quoted argument, make sure we get it all from command-line. */
IF POS('"', GetOpt.i) > 0 THEN DO
cnt = count('"',GetOpt.i)
PARSE VAR GetOpt.i opt '"' tmparg
GetOpt.i = opt || STRIP(tmparg, 'T', '"')
IF cnt = 1 THEN DO
PARSE VAR arglist remarg '"' arglist
GetOpt.i = GetOpt.i remarg
END
END
END
GetOpt.0 = i
RETURN GetOpt.0
/* End of SetupArg */