home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-01-06 | 43.6 KB | 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 */
-