home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cppdoc.zip / cppdoc.cmd next >
OS/2 REXX Batch file  |  1997-01-06  |  45KB  |  1,216 lines

  1. /* --------------------------------------------------------------------------
  2.  * $RCSfile: cppdoc.cmd,v $
  3.  * $Revision: 1.11 $
  4.  * $Date: 1997/01/06 15:07:16 $
  5.  * $Author: Bablok $
  6.  * --------------------------------------------------------------------------
  7.  * Synopsis:
  8.  *
  9.  * Documentation-Generator for C++ programs.
  10.  *
  11.  * cppdoc.cmd and cppdoc.htm are Copyright (c) 1996 by Bernhard Bablok
  12.  * --------------------------------------------------------------------------
  13.  * History:
  14.  *
  15.  * $Log: cppdoc.cmd,v $
  16.  * Revision 1.11  1997/01/06 15:07:16  Bablok
  17.  * added expandTabs-subroutine to replace tabs with blanks in input files
  18.  *
  19.  * Revision 1.10  1996/09/07 16:26:57  Bablok
  20.  * Various new features
  21.  * New commandline interface
  22.  *
  23.  * Revision 1.0  1996/06/06 14:25:36  Bablok
  24.  * Initial revision
  25.  *
  26.  * -------------------------------------------------------------------------- */
  27.  
  28. PARSE ARG cmdLine
  29.  
  30. CALL initConstants
  31. CALL processArgs
  32. CALL readIndex
  33. DO numCycles
  34.    DO fileNr = GetOpt._optind TO GetOpt.0
  35.       CALL initVars GetOpt.fileNr
  36.       CALL readFiles
  37.       CALL findClasses
  38.       CALL findMember
  39.       CALL printDoc
  40.    END
  41. END
  42. CALL updateIndexFile
  43. RETURN 0
  44.  
  45. /* -------------------------------------------------------------------------- */
  46. /* some utility functions, for performance reasons at the head of the file    */
  47. /* -------------------------------------------------------------------------- */
  48.  
  49. /*----------------------------------------------------------------------------*/
  50. /* expandTabs: Expand tabs to blanks                                          */
  51. /*----------------------------------------------------------------------------*/
  52. expandTabs: PROCEDURE
  53.  
  54. tabInterval = 3
  55. tabChar     = D2C(9)
  56. PARSE ARG string
  57.  
  58. tabPos = POS(tabChar,string)
  59. DO WHILE tabPos > 0
  60.    tabOffset = tabPos//tabInterval
  61.    PARSE VALUE string WITH head (tabChar) tail
  62.    IF tabOffset = 0 THEN
  63.       string = head tail
  64.    ELSE
  65.       string = head || COPIES(' ',tabInterval+1-tabOffset) || tail
  66.    tabPos = POS(tabChar,string)
  67. END
  68. RETURN string
  69.  
  70. /* -------------------------------------------------------------------------- */
  71. /* nextIdentifier: return position of next identifier and identifier          */
  72. /*                 of a given string                                          */
  73. /* -------------------------------------------------------------------------- */
  74. nextIdentifier: PROCEDURE
  75.  
  76. PARSE ARG string, start
  77.  
  78. IF string = '' THEN
  79.   RETURN 0 ''
  80. IF start = '' THEN
  81.   start = 1
  82. IF start > LENGTH(string) THEN
  83.   RETURN 0 ''
  84.  
  85. string = SUBSTR(string,start)
  86. first = VERIFY(string,'_abcdefghijklmnopqrstuvwxyz' ||,
  87.                                      'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789','M')
  88. IF first = 0 THEN
  89.   RETURN 0 ''
  90.  
  91. string = SUBSTR(string,first)
  92. len = VERIFY(string,'_abcdefghijklmnopqrstuvwxyz' ||,
  93.                                      'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') - 1
  94. IF len = -1 THEN
  95.   len = LENGTH(string)
  96. ident = SUBSTR(string,1,len)
  97. IF ident = 'operator' & POS('(',string,len+1) > 2 THEN
  98.   ident = SPACE(SUBSTR(string,1,POS('(',string,len+1)-1),0)
  99.  
  100. RETURN start+first-1 ident
  101.  
  102. /* -------------------------------------------------------------------------- */
  103. /* lastIdentifier: return last (c++)-identifier in a given string             */
  104. /*                  (including ~ for destructor, expecting no bitwise NOT)    */
  105. /* -------------------------------------------------------------------------- */
  106. lastIdentifier: PROCEDURE
  107.  
  108. PARSE ARG string, start
  109.  
  110. IF string = '' THEN
  111.   RETURN ''
  112. IF start = '' THEN
  113.   start = LENGTH(string)
  114.  
  115. revString = REVERSE(STRIP(SUBSTR(string,1,start)))
  116. first = VERIFY(revString,'~_abcdefghijklmnopqrstuvwxyz' ||,
  117.                                      'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789','M')
  118. IF first = 0 THEN
  119.   RETURN ''
  120. len = VERIFY(SUBSTR(revString,first),'~_abcdefghijklmnopqrstuvwxyz' ||,
  121.                                      'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') - 1
  122. IF len = -1 THEN
  123.   len = LENGTH(revString) - (first-1)
  124. ident = REVERSE(SUBSTR(revString,first,len))
  125. IF ident = 'operator' THEN DO
  126.   ident = STRIP(REVERSE(STRIP(SUBSTR(revString,1,len+first-1),'L','(')))
  127. END                                          /* IF ident = 'operator' THEN DO */
  128. RETURN ident
  129.  
  130. /* -------------------------------------------------------------------------- */
  131. /* findMatchingChar: find position of closing parenthesis, brace etc          */
  132. /* -------------------------------------------------------------------------- */
  133. findMatchingChar: PROCEDURE
  134.  
  135. PARSE ARG string, start
  136.  
  137. cOpen = SUBSTR(string,start,1)
  138. SELECT
  139.   WHEN cOpen = '(' THEN cClose = ')'
  140.   WHEN cOpen = '{' THEN cClose = '}'
  141.   WHEN cOpen = '[' THEN cClose = ']'
  142.   WHEN cOpen = '<' THEN cClose = '>'
  143.   WHEN cOpen = ')' THEN cClose = '('
  144.   WHEN cOpen = '}' THEN cClose = '{'
  145.   WHEN cOpen = ']' THEN cClose = '['
  146.   WHEN cOpen = '>' THEN cClose = '<'
  147.   OTHERWISE
  148.     RETURN 0
  149. END                                                                 /* SELECT */
  150. IF POS(cOpen,')}]>') > 0 THEN DO
  151.   string = REVERSE(string)
  152.   start  = LENGTH(string) - start + 1
  153. END                                       /* IF POS(cOpen,')}]>') > 0 THEN DO */
  154.  
  155. open = 1
  156. next = 0
  157. DO FOREVER
  158.   charPos = VERIFY(SUBSTR(string,start+next+1),cOpen||cClose,'M')
  159.   IF charPos = 0 THEN                           /* actually, this is an error */
  160.     RETURN 0
  161.   next = next + charPos
  162.   char = SUBSTR(string,start+next,1)
  163.   IF char = cOpen THEN
  164.     open = open + 1
  165.   ELSE
  166.     open = open - 1
  167.   IF open = 0 THEN DO
  168.     matchingPos = start + next
  169.     IF POS(cOpen,')}]>') > 0 THEN
  170.       matchingPos = LENGTH(string) - matchingPos + 1
  171.     RETURN matchingPos
  172.   END                                                  /* IF open = 0 THEN DO */
  173. END                                                             /* DO FOREVER */
  174.  
  175. /* -------------------------------------------------------------------------- */
  176. /* makeExternalRef: add anchor tag for external reference                     */
  177. /* -------------------------------------------------------------------------- */
  178. makeExternalRef: PROCEDURE EXPOSE externalRefs. className
  179.  
  180. PARSE ARG line
  181.  
  182. start = 1
  183. CALL nextIdentifier line, start
  184. PARSE VALUE RESULT WITH identPos ident
  185. DO WHILE ident <> ''
  186.   IF externalRefs.ident <> '' & ident <> className THEN DO
  187.     ref  = '<A HREF="'externalRefs.ident'">'ident'</A>'
  188.     head = SUBSTR(line,1,identPos-1)
  189.     tail = SUBSTR(line,identPos+LENGTH(ident))
  190.     line = head || ref || tail
  191.     identPos = identPos + LENGTH(externalRefs.ident) + 15
  192.   END             /* IF externalRefs.ident <> '' & ident <> className THEN DO */
  193.   start = identPos + LENGTH(ident)
  194.   CALL nextIdentifier line, start
  195.   PARSE VALUE RESULT WITH identPos ident
  196. END                                                   /* DO WHILE ident <> '' */
  197. RETURN line
  198.  
  199. /* -------------------------------------------------------------------------- */
  200. /* makeInternalRef: add anchor tag for internal reference                     */
  201. /* -------------------------------------------------------------------------- */
  202. makeInternalRef: PROCEDURE
  203.  
  204. PARSE ARG string, refToken, refAnchor
  205.  
  206. ref = '<A HREF="#'refAnchor'">'refToken'</A>'
  207. PARSE VALUE string WITH head (refToken) tail
  208. RETURN head || ref || tail
  209.  
  210. /* -------------------------------------------------------------------------- */
  211. /* lastWord: return last word of given string                                 */
  212. /* -------------------------------------------------------------------------- */
  213. lastWord: PROCEDURE
  214.  
  215. PARSE ARG string
  216. RETURN WORD(string,WORDS(string))
  217.  
  218. /* -------------------------------------------------------------------------- */
  219. /* count: Return count of a given character in a given string                 */
  220. /* -------------------------------------------------------------------------- */
  221. count: PROCEDURE
  222.  
  223. PARSE ARG c, string
  224.  
  225. start = 1
  226. num   = 0
  227. DO FOREVER
  228.   col = POS(c,string,start)
  229.   IF col > 0 THEN DO
  230.     num   = num + 1
  231.     start = col + 1
  232.   END                                                   /* IF col > 0 THEN DO */
  233.   ELSE
  234.     RETURN num
  235. END                                                             /* DO FOREVER */
  236.  
  237. /* -------------------------------------------------------------------------- */
  238. /* changestr: Change multiple occurences of a given string                    */
  239. /* -------------------------------------------------------------------------- */
  240. changestr: PROCEDURE
  241.  
  242. PARSE ARG string, tableo, tablei, start, delim, once
  243.  
  244. IF start = '' THEN
  245.   start = 1
  246. IF delim = '' THEN
  247.   delim = ' '
  248. IF once = '' THEN
  249.   once = 0
  250.  
  251. DO FOREVER
  252.   IF tablei = '' THEN
  253.     LEAVE
  254.   PARSE VALUE tablei WITH oldToken (delim) tablei
  255.   PARSE VALUE tableo WITH newToken (delim) tableo
  256.   DO FOREVER
  257.     IF POS(oldToken,string,start) = 0 THEN
  258.       LEAVE
  259.     PARSE VALUE SUBSTR(string,start) WITH head (oldToken) rest
  260.     IF start > 1 THEN
  261.       string = SUBSTR(string,1,start-1) || head || newToken || rest
  262.     ELSE
  263.       string = head || newToken || rest
  264.     IF once THEN
  265.       LEAVE
  266.   END                                                           /* DO FOREVER */
  267. END                                                             /* DO FOREVER */
  268. RETURN string
  269.  
  270. /* -------------------------------------------------------------------------- */
  271. /* initConstants: Define constants                                            */
  272. /* -------------------------------------------------------------------------- */
  273. initConstants:
  274.  
  275. MSG_READ_FILES        = "Reading files ..."
  276. MSG_READ_INDEX        = "Reading index"
  277. MSG_FIND_CLASSES      = "Looking for class declarations"
  278. MSG_FIND_MEMBER       = "Looking for member definitions"
  279. MSG_PRINT_DOC         = "Generating documentation..."
  280. MSG_PRINT_DESC        = "... class description"
  281. MSG_PRINT_INHER       = "... class inheritance"
  282. MSG_CLASS_INTERFACE   = "... class interface"
  283. MSG_MEMBER_DOC        = "... member description"
  284. ERR_TARGET_DIR        = "Error: Target directory does not exist"
  285. ERR_FILE_NOT_FOUND    = "Error: File" fileName "not found"
  286. ERR_NO_FILES          = "Error: No files"
  287. ERR_INVALID_INDEX     = "Error: Index-file" indexFile "is invalid"
  288. ERR_UNBALANCED_BRACES = "Error: Missing '}'"
  289.  
  290. DOC_TITLE       = 'Class Documentation for C++-Class: '
  291. SOURCE_H2       = 'Source'
  292. CLASS_INH_H2    = 'Inheritance'
  293. CLASS_DOC_H2    = 'Class Description'
  294. CLASS_DOC_NONE  = 'No description available.'
  295. CLASS_INT_H2    = 'Class Interface'
  296. CLASS_INT_REF   = 'Return to class interface.'
  297. CLASS_INT_NONE  = 'Class declaration not found.'
  298. MEMBER_DOC_H2   = 'Description of Functions (Members and Others)'
  299. MEMBER_DOC_NONE = 'No details about members available.'
  300. INDEX_TITLE     = 'Index to C++-Class Documentation'
  301. INDEX_H1        = 'Index'
  302.  
  303.  
  304. CPP_EXTENSIONS  = 'cpp cc cxx c'
  305. NLS_CHAR_ESC    = 'ä ö ü Ä Ö Ü ß'
  306. NLS_CHAR        = 'ä ö ü Ä Ö Ü ß'
  307. MAX_LINE_LENGTH = 70
  308.  
  309. CALL RxFuncAdd 'SysFileDelete', 'RexxUtil', 'SysFileDelete'
  310. CALL RxFuncAdd 'SysFileTree', 'RexxUtil', 'SysFileTree'
  311. RETURN
  312.  
  313. /* -------------------------------------------------------------------------- */
  314. /* processArgs: process command line arguments, setup variables               */
  315. /* -------------------------------------------------------------------------- */
  316. processArgs:
  317.  
  318. CALL setupArg cmdLine
  319. GetOpt._opterr = 0
  320.  
  321. printAll            = 1
  322. printSource         = 0
  323. printDesc           = 0
  324. printInter          = 0
  325. printMem            = 0
  326. omitTrailer         = 0
  327. numCycles           = 1
  328. relativeLinks       = 0
  329. targetDirectory     = '.'
  330. indexFile           = ''
  331. hidePrivateSections = 0
  332. optstr              = 'x:t:r2Hsdimo'
  333.  
  334. DO UNTIL c = -1 | c = '?'
  335.   c = GetOpt(optstr)
  336.   SELECT
  337.     WHEN c = 'x' THEN
  338.       indexFile = GetOpt._optarg
  339.     WHEN c = 't' THEN
  340.       targetDirectory = STRIP(GetOpt._optarg,'T','\')
  341.     WHEN c = 'r' THEN
  342.       relativeLinks = 1
  343.     WHEN c = '2' THEN
  344.       numCycles = 2
  345.     WHEN c = 'H' THEN
  346.       hidePrivateSections = 1
  347.     WHEN c = 's' THEN DO
  348.       printAll    = 0
  349.       printSource = 1
  350.     END
  351.     WHEN c = 'd' THEN DO
  352.       printAll    = 0
  353.       printDesc   = 1
  354.     END
  355.     WHEN c = 'i' THEN DO
  356.       printAll    = 0
  357.       printInter  = 1
  358.     END
  359.     WHEN c = 'm' THEN DO
  360.       printAll    = 0
  361.       printMem    = 1
  362.     END
  363.     WHEN c = 'o' THEN
  364.       omitTrailer = 1
  365.     WHEN c = '?' THEN
  366.       CALL usage
  367.     OTHERWISE
  368.       NOP
  369.   END
  370. END
  371. IF printAll THEN DO
  372.   printSource = 1
  373.   printDesc   = 1
  374.   printInter  = 1
  375.   printMem    = 1
  376. END
  377.  
  378. curDir = DIRECTORY()
  379. targetDirectory = DIRECTORY(targetDirectory)
  380. CALL DIRECTORY curDir
  381. IF targetDirectory = '' THEN DO
  382.   SAY ERR_TARGET_DIR
  383.   EXIT 3
  384. END
  385. ELSE
  386.   targetDirectory = targetDirectory'\'
  387. IF indexFile <> '' THEN
  388.   indexFile = targetDirectory || indexFile
  389.  
  390. /* process filename arguments   --------------------------------------------- */
  391.  
  392. i = GetOpt._optind
  393. DO WHILE i <= GetOpt.0
  394.    IF POS('*',GetOpt.i) > 0 | POS('?',GetOpt.i) > 0 THEN DO
  395.       CALL SysFileTree GetOpt.i,'files.','FO'
  396.       DO j = i+1 TO GetOpt.0
  397.          k = j - 1
  398.          GetOpt.k = GetOpt.j
  399.       END
  400.       DO j = 1 TO files.0
  401.          k = GetOpt.0 - 1 + j
  402.          GetOpt.k = files.j
  403.       END
  404.       GetOpt.0 = GetOpt.0 + files.0 - 1
  405.    END
  406.    ELSE
  407.       i = i + 1
  408. END
  409. IF GetOpt._optind > GetOpt.0 THEN DO
  410.   SAY ERR_NO_FILES
  411.   CALL usage
  412. END
  413.  
  414. RETURN
  415.  
  416. /* -------------------------------------------------------------------------- */
  417. /* initVars: Initialize Variables                                             */
  418. /* -------------------------------------------------------------------------- */
  419. initVars:
  420.  
  421. PARSE ARG fileName
  422. fileName = STREAM(fileName,'C','query exists')
  423. IF fileName = '' THEN DO
  424.   SAY ERR_FILE_NOT_FOUND
  425.   EXIT 3
  426. END                                               /* IF fileName = '' THEN DO */
  427. sourceFiles = '<A HREF="file:///'fileName'">'fileName'</A>'
  428.  
  429. classList       = ''
  430. classDocu.      = ''
  431. classInterf.    = ''
  432. classInherit.   = ''
  433. classBase.      = ''
  434. classMember.    = ''
  435. memberDef.      = ''
  436. memberDocu.     = ''
  437.  
  438. RETURN 0
  439.  
  440. /* -------------------------------------------------------------------------- */
  441. /* readFiles: Read interface and implementation files                         */
  442. /* -------------------------------------------------------------------------- */
  443. readFiles:
  444.  
  445. SAY MSG_READ_FILES
  446.  
  447. i = 0
  448. SAY '...' fileName
  449. DO WHILE LINES(fileName) > 0
  450.   i = i + 1
  451.   line.i = STRIP(expandTabs(LINEIN(fileName)),'T')
  452.   IF line.i = '' THEN DO
  453.     i = i - 1
  454.     ITERATE
  455.   END                                               /* IF line.i = '' THEN DO */
  456.   ELSE IF WORD(line.i,1) = '#define' THEN DO
  457.     DO UNTIL RIGHT(line.i,1) <> '\'
  458.       line.i = STRIP(expandTabs(LINEIN(fileName)),'T')
  459.     END                                    /* DO UNTIL RIGHT(line.i,1) <> '\' */
  460.     i = i - 1
  461.     ITERATE
  462.   END
  463.   ELSE IF LEFT(STRIP(line.i),4) = '//@p' THEN DO
  464.     IF hidePrivateSections THEN DO
  465.       i = i - 1
  466.       ITERATE
  467.     END
  468.     ELSE DO
  469.       ppos = POS('//@p',line.i) + 3
  470.       line.i = OVERLAY(' ',line.i,ppos)
  471.     END
  472.   END
  473. END                                           /* DO WHILE LINES(fileName) > 0 */
  474. CALL LINEOUT fileName
  475.  
  476. DO j = 1 TO WORDS(CPP_EXTENSIONS)
  477.   impFile = SUBSTR(fileName,1,LASTPOS('.',fileName)) || WORD(CPP_EXTENSIONS,j)
  478.   impFile = STREAM(impFile,'C','query exists')
  479.   IF impFile <> '' THEN DO
  480.     SAY '...' impFile
  481.     sourceFiles = sourceFiles',' '<A HREF="file:///'impFile'">'impFile'</A>'
  482.     DO WHILE LINES(impFile) > 0
  483.       i = i + 1
  484.       line.i = STRIP(expandTabs(LINEIN(impFile)))
  485.       IF line.i = '' THEN DO
  486.         i = i - 1
  487.         ITERATE
  488.       END                                           /* IF line.i = '' THEN DO */
  489.       ELSE IF WORD(line.i,1) = '#define' THEN DO
  490.         DO UNTIL RIGHT(line.i,1) <> '\'
  491.           line.i = STRIP(expandTabs(LINEIN(impFile)),'T')
  492.         END                                /* DO UNTIL RIGHT(line.i,1) <> '\' */
  493.         i = i - 1
  494.         ITERATE
  495.       END                                /* DO UNTIL RIGHT(line.i,1) <> '\' */
  496.       ELSE IF LEFT(line.i,4) = '//@p' THEN DO
  497.         IF hidePrivateSections THEN DO
  498.           i = i - 1
  499.           ITERATE
  500.         END
  501.         ELSE DO
  502.           ppos = POS('//@p',line.i) + 3
  503.           line.i = OVERLAY(' ',line.i,ppos)
  504.         END
  505.       END
  506.     END                                        /* DO WHILE LINES(impFile) > 0 */
  507.     CALL LINEOUT impFile
  508.     LEAVE
  509.   END                                             /* IF impFile <> '' THEN DO */
  510. END                                      /* DO j = 1 TO WORDS(CPP_EXTENSIONS) */
  511. line.0 = i
  512. lastLine = line.0   /* default value, in case file does not contain class def */
  513. RETURN
  514.  
  515. /* -------------------------------------------------------------------------- */
  516. /* readIndex: Read index file                                                 */
  517. /* -------------------------------------------------------------------------- */
  518. readIndex:
  519.  
  520. indexAddBefore = 0
  521. externalRefsClassList = ''
  522. externalRefs.         = ''
  523. classIndexInfo.       = ''
  524.  
  525. IF indexFile <> '' THEN DO
  526.   IF POS('.',indexFile,LASTPOS('\',indexFile)+1) = 0 THEN
  527.     indexFile = STRIP(indexFile)'.htm'
  528.   IF STREAM(indexFile,'C','query exists') <> '' THEN DO
  529.     i = 0
  530.     SAY MSG_READ_INDEX indexFile
  531.     DO WHILE LINES(indexFile)
  532.       i = i + 1
  533.       index.i = expandTabs(LINEIN(indexFile))
  534.       index.i._class = '---'
  535.       IF LEFT(STRIP(index.i),4) = '<LI>' THEN DO
  536.         PARSE VALUE index.i WITH . '"' classNameFile '">' className '<' .
  537.         index.i._class = className
  538.         externalRefs.className = classNameFile
  539.       END                       /* IF LEFT(STRIP(index.i),4) = '<LI>' THEN DO */
  540.       ELSE IF LEFT(STRIP(index.i),5) = '</UL>' THEN
  541.         indexAddBefore = i
  542.     END                                          /* DO WHILE LINES(indexFile) */
  543.     CALL LINEOUT indexFile
  544.     index.0 = i
  545.     IF indexAddBefore = 0 THEN DO
  546.       SAY ERR_INVALID_INDEX
  547.       EXIT 3
  548.     END                                      /* IF indexAddBefore = 0 THEN DO */
  549.   END                /* IF STREAM(indexFile,'C','query exists') <> '' THEN DO */
  550. END                                             /* IF indexFile <> '' THEN DO */
  551. RETURN
  552.  
  553. /* -------------------------------------------------------------------------- */
  554. /* findClasses: find class declarations                                       */
  555. /* -------------------------------------------------------------------------- */
  556. findClasses:
  557.  
  558. SAY MSG_FIND_CLASSES
  559.  
  560. comment = 0
  561. DO i = 1 TO line.0
  562.  
  563.   /* skip comment lines   --------------------------------------------------- */
  564.  
  565.   IF LEFT(STRIP(line.i),2) = '//' THEN
  566.     ITERATE
  567.   ELSE IF comment & POS('*/',line.i) = 0 THEN
  568.     ITERATE
  569.   ELSE IF comment THEN DO
  570.     comment = 0
  571.     ITERATE
  572.   END                                              /* ELSE IF comment THEN DO */
  573.   ELSE IF POS('/*',line.i) > 0 & POS('*/',line.i) = 0 THEN DO
  574.     comment = 1
  575.     ITERATE
  576.   END          /* ELSE IF POS('/*',line.i) > 0 & POS('*/',line.i) = 0 THEN DO */
  577.   ELSE IF POS('/*',line.i) > 0 THEN
  578.     ITERATE
  579.  
  580.   /* check if class token is present   -------------------------------------- */
  581.  
  582.   IF POS('class',line.i) > 0 THEN DO
  583.  
  584.     /* concatenate lines until end of statement or beginning of declaration */
  585.  
  586.     line = line.i
  587.     n = i - 1
  588.     DO WHILE i < line.0 & POS(';',line) = 0 & POS('{',line) = 0
  589.       i = i + 1
  590.       line = line line.i
  591.     END        /* DO WHILE i < line.0 & POS(';',line) = 0 & POS('{',line) = 0 */
  592.  
  593.     /* omit template definitions of functions   ----------------------------- */
  594.  
  595.     IF WORDPOS('template',line) > 0 THEN DO
  596.       lt = POS('<',line)
  597.       IF WORDPOS('class',SUBSTR(line,findMatchingChar(line,lt))) = 0 THEN
  598.         ITERATE
  599.     END                            /* IF WORDPOS('template',line) > 0 THEN DO */
  600.  
  601.     /* omit forward declarations   ------------------------------------------ */
  602.  
  603.     IF POS('{',line) > 0 THEN DO                 /* found a class declaration */
  604.       IF POS(':',line) = 0 THEN DO               /* no classes inherited from */
  605.         PARSE VALUE line WITH this '{' .
  606.         className = lastWord(this)
  607.         classInherit.className = this
  608.       END                                     /* IF POS(':',line) = 0 THEN DO */
  609.       ELSE DO
  610.         PARSE VALUE line WITH this ':' base '{' .
  611.         className = lastWord(this)
  612.         classInherit.className = this ':' base
  613.       END                                                          /* ELSE DO */
  614.       classList = classList className
  615.       IF WORDPOS(className,externalRefsClassList) = 0 THEN
  616.         externalRefsClassList = externalRefsClassList className
  617.       IF relativeLinks THEN
  618.         externalRefs.className = className'.htm'
  619.       ELSE
  620.         externalRefs.className = 'file:///'targetDirectory||className'.htm'
  621.       CALL findClassDocu className, n
  622.       CALL findClassInterface className, line
  623.     END                                       /* IF POS('{',line) > 0 THEN DO */
  624.   END                                   /* IF POS('class',line.i) > 0 THEN DO */
  625. END                                                     /* DO i = 1 TO line.0 */
  626. RETURN
  627.  
  628. /* -------------------------------------------------------------------------- */
  629. /* findClassDocu: extract class documentation                                 */
  630. /* -------------------------------------------------------------------------- */
  631. findClassDocu: PROCEDURE EXPOSE line. classDocu. classIndexInfo.
  632.  
  633. PARSE ARG className, n
  634.  
  635. DO i = n TO 1 BY -1 UNTIL LEFT(STRIP(line.i),3) = '//@'
  636. END                /* DO i = n TO 1 BY -1 UNTIL LEFT(STRIP(line.i),3) = '//@' */
  637. IF i > 0 THEN DO
  638.   j = 0
  639.   DO WHILE i > 0 & LEFT(STRIP(line.i),3) = '//@'
  640.     j = j + 1
  641.     classDocu.className.j = STRIP(SUBSTR(STRIP(line.i),4))
  642.     i = i - 1
  643.   END                       /* DO WHILE i > 0 & LEFT(STRIP(line.i),3) = '//@' */
  644.   classIndexInfo.className = classDocu.className.j
  645.   classDocu.className.0 = j - 1
  646. END                                                       /* IF i > 0 THEN DO */
  647. ELSE
  648.   classDocu.className.0 = 0
  649. RETURN
  650.  
  651. /* -------------------------------------------------------------------------- */
  652. /* findClassInterface: extract class interface                                */
  653. /* -------------------------------------------------------------------------- */
  654. findClassInterface: PROCEDURE EXPOSE line. classInterf. i lastLine
  655.  
  656. PARSE ARG className, line
  657.  
  658. line.i = STRIP(SUBSTR(line' ',POS('{',line)+1))
  659. IF line.i = '' THEN
  660.   i = i + 1
  661. open = 1
  662. j = 0
  663. DO i = i TO line.0
  664.   open = open + count('{',line.i) - count('}',line.i)
  665.   IF open < 0  THEN DO
  666.     SAY ERR_UNBALANCED_BRACES
  667.     EXIT 3
  668.   END                                                 /* IF open < 0  THEN DO */
  669.   ELSE IF open = 0 THEN DO
  670.     endPos = LASTPOS('}',line.i)                  /* ELSE IF open = 0 THEN DO */
  671.     line = STRIP(SUBSTR(line.i,1,endPos-1))
  672.     IF line <> '' THEN DO
  673.       j = j + 1
  674.       classInterf.className.j = line
  675.     END                                              /* IF line <> '' THEN DO */
  676.     LEAVE i
  677.   END                                             /* ELSE IF open = 0 THEN DO */
  678.   ELSE DO
  679.     j = j + 1
  680.     classInterf.className.j = line.i
  681.   END                                                              /* ELSE DO */
  682. END                                                     /* DO i = i TO line.0 */
  683. lastLine = i
  684. classInterf.className.0 = j
  685. RETURN
  686.  
  687. /* -------------------------------------------------------------------------- */
  688. /* findMember: locate member definition                                       */
  689. /* -------------------------------------------------------------------------- */
  690. findMember:
  691.  
  692. SAY MSG_FIND_MEMBER
  693.  
  694. DO i = lastLine + 1 TO line.0
  695.  
  696.   /* skip lines before next docu-block   ------------------------------------ */
  697.  
  698.   DO WHILE i <= line.0 & LEFT(STRIP(line.i),3) <> '//@'
  699.     i = i + 1
  700.     ITERATE
  701.   END                /* DO WHILE i <= line.0 & LEFT(STRIP(line.i),3) <> '//@' */
  702.  
  703.   /* read docu-block   ------------------------------------------------------ */
  704.  
  705.   IF i <= line.0 & LEFT(STRIP(line.i),3) = '//@'  THEN DO
  706.     j = 0
  707.     DO WHILE i <= line.0 & LEFT(STRIP(line.i),3) = '//@'
  708.       j = j + 1
  709.       doc.j = STRIP(SUBSTR(STRIP(line.i),4))
  710.       i = i + 1
  711.     END               /* DO WHILE i <= line.0 & LEFT(STRIP(line.i),3) = '//@' */
  712.     doc.0 = j
  713.   END              /* IF i <= line.0 & LEFT(STRIP(line.i),3) = '//@'  THEN DO */
  714.  
  715.   /* read member definition   ----------------------------------------------- */
  716.  
  717.   IF i <= line.0 THEN DO
  718.     line = STRIP(line.i)
  719.     line = changestr(line,'°°','::')
  720.     DO WHILE i <= line.0 & POS('{',line) = 0 & POS(':',line) = 0
  721.       i = i + 1
  722.       line = line STRIP(line.i)
  723.       line = changestr(line,'°°','::')
  724.     END       /* DO WHILE i <= line.0 & POS('{',line) = 0 & POS(':',line) = 0 */
  725.     IF POS(':',line) > 0 THEN
  726.       line = STRIP(SUBSTR(line,1,POS(':',line)-1))  /* this is a constructor! */
  727.     ELSE
  728.       line = STRIP(SUBSTR(line,1,POS('{',line)-1))
  729.     line = changestr(line,'::','°°')
  730.  
  731.     /* try to find a function/member definition   --------------------------- */
  732.  
  733.     start = findMatchingChar(line,LASTPOS(')',line))-1
  734.     memberName = SPACE(lastIdentifier(line,start),0)
  735.     start = start - LENGTH(memberName) -,
  736.                       POS(REVERSE(memberName),REVERSE(SUBSTR(line,1,start))) + 1
  737.     IF RIGHT(STRIP(SUBSTR(line,1,start)),2) = '::' THEN DO       /* a member! */
  738.       col = LASTPOS('::',line,start)
  739.       DO WHILE col > 0
  740.         IF RIGHT(STRIP(SUBSTR(line,1,col-1)),1) = '>' THEN      /* a template */
  741.           col = findMatchingChar(line,LASTPOS('>',line,col-1))
  742.         ident = lastIdentifier(line,col-1)
  743.         IF WORDPOS(ident,classList) > 0 THEN DO
  744.           className = ident
  745.           LEAVE
  746.         END                        /* IF WORDPOS(ident,classList) > 0 THEN DO */
  747.         ELSE
  748.           col = LASTPOS('::',line,col-1)
  749.       END                                                 /* DO WHILE col > 0 */
  750.     END             /* IF RIGHT(STRIP(SUBSTR(line,1,start)),2) = '::' THEN DO */
  751.  
  752.     memberName = changestr(memberName,'°amp; < >','& < >')
  753.     memberName = changestr(memberName,'&','°')
  754.     IF WORDPOS(memberName,classMember.className) > 0 THEN
  755.       memberName = memberName'!'i                              /* overloaded! */
  756.     classMember.className = classMember.className memberName
  757.     DO j=1 TO doc.0
  758.       memberDocu.className.memberName.j = doc.j
  759.     END                                                    /* DO j=1 TO doc.0 */
  760.     memberDocu.className.memberName.0 = doc.0
  761.     memberDef.className.memberName = line
  762.  
  763.   END                                               /* IF i <= line.0 THEN DO */
  764. END                                          /* DO i = lastLine + 1 TO line.0 */
  765. RETURN
  766.  
  767. /* -------------------------------------------------------------------------- */
  768. /* printDoc: generate HTML-file                                               */
  769. /* -------------------------------------------------------------------------- */
  770. printDoc:
  771.  
  772. DO i = 1 TO WORDS(classList)
  773.   className = WORD(classList,i)
  774.   docFile   = targetDirectory||className'.htm'
  775.   SAY MSG_PRINT_DOC className '...'
  776.   CALL SysFileDelete docFile
  777.   CALL printHeader
  778.   IF printSource THEN
  779.     CALL LINEOUT docFile, '<H2>'SOURCE_H2'</H2><P>'sourceFiles'<P><HR>'
  780.   IF printDesc THEN
  781.     CALL printClassDoc
  782.   IF printInter THEN DO
  783.     CALL printClassInheritance
  784.     CALL printClassInterface
  785.   END
  786.   IF printMem THEN
  787.     CALL printMemberDoc
  788.   CALL printTrailer docFile
  789.   CALL LINEOUT docFile
  790. END                                           /* DO i = 1 TO WORDS(classList) */
  791. RETURN
  792.  
  793. /* -------------------------------------------------------------------------- */
  794. /* printHeader: header for HTML-file, including source and inheritance        */
  795. /* -------------------------------------------------------------------------- */
  796. printHeader:
  797.  
  798. CALL LINEOUT docFile, '<!-- Class documentation generated by CPPDOC -->'
  799. CALL LINEOUT docFile, '<HTML>'
  800. CALL LINEOUT docFile, '<HEAD>'
  801. CALL LINEOUT docFile, '<TITLE>'DOC_TITLE className'</TITLE>'
  802. CALL LINEOUT docFile, '</HEAD>'
  803. CALL LINEOUT docFile, '<BODY>'
  804. CALL LINEOUT docFile, '<H1>Class' className'</H1>'
  805. RETURN
  806.  
  807. /* -------------------------------------------------------------------------- */
  808. /* printClassInheritance: Class inheritance                                   */
  809. /* -------------------------------------------------------------------------- */
  810. printClassInheritance:
  811.  
  812. SAY MSG_PRINT_INHER
  813.  
  814. CALL LINEOUT docFile, '<H2>'CLASS_INH_H2'</H2>'
  815.  
  816. indent = 0
  817. CALL LINEOUT docFile, '<P><PRE>'
  818. def = classInherit.className
  819. DO WHILE LENGTH(def) > MAX_LINE_LENGTH
  820.   splitPos = LASTPOS(',',def,MAX_LINE_LENGTH)
  821.   IF splitPos = 0 THEN
  822.     splitPos = LASTPOS(' ',def,MAX_LINE_LENGTH)
  823.   token = changestr(SUBSTR(def,1,splitPos),'°amp; < >','& < >')
  824.   token = changestr(token,'&','°')
  825.   def   = STRIP(SUBSTR(def,splitPos+1))
  826.   CALL LINEOUT docFile, COPIES(' ',indent) makeExternalRef(token)
  827.   indent = 5
  828. END                                 /* DO WHILE LENGTH(def) > MAX_LINE_LENGTH */
  829. def = changestr(def,'°amp; < >','& < >')
  830. def = changestr(def,'&','°')
  831. CALL LINEOUT docFile, COPIES(' ',indent) makeExternalRef(def)
  832. CALL LINEOUT docFile, '</PRE></P>'
  833.  
  834.  
  835. CALL LINEOUT docFile, '<HR>'
  836. RETURN
  837.  
  838. /* -------------------------------------------------------------------------- */
  839. /* printClassDoc: class description                                           */
  840. /* -------------------------------------------------------------------------- */
  841. printClassDoc:
  842.  
  843. SAY MSG_PRINT_DESC
  844.  
  845. CALL LINEOUT docFile, '<H2>'CLASS_DOC_H2'</H2><P>'
  846. IF classDocu.className.0 = 0 THEN
  847.   CALL LINEOUT docFile, CLASS_DOC_NONE
  848. ELSE
  849.   DO j = classDocu.className.0 TO 1 BY -1
  850.     CALL LINEOUT docFile,,
  851.                           changestr(classDocu.className.j,NLS_CHAR_ESC,NLS_CHAR)
  852.   END                              /* DO j = classDocu.className.0 TO 1 BY -1 */
  853. CALL LINEOUT docFile, '</P><HR>'
  854. RETURN
  855.  
  856. /* -------------------------------------------------------------------------- */
  857. /* printClassInterface: class interface                                       */
  858. /* -------------------------------------------------------------------------- */
  859. printClassInterface:
  860.  
  861. SAY MSG_CLASS_INTERFACE
  862.  
  863. CALL LINEOUT docFile, '<H2><A NAME="'CLASS_INT_H2'">'CLASS_INT_H2'</A></H2><P>'
  864. IF classInterf.className.0 = 0 THEN
  865.   CALL LINEOUT docFile, CLASS_INT_NONE
  866. ELSE DO
  867.   CALL LINEOUT docFile, '<PRE>'
  868.   doneInternalLinks = ''
  869.  
  870.   comment = 0
  871.   DO j=1 TO classInterf.className.0
  872.     line = classInterf.className.j
  873.  
  874.     /* skip comment lines   ----------------------------------------------- */
  875.  
  876.     IF LEFT(STRIP(line),2) = '//' THEN DO
  877.       line = changestr(line,'°amp; < >','& < >')
  878.       line = changestr(line,'&','°')
  879.       CALL LINEOUT docFile, changestr(line,NLS_CHAR_ESC,NLS_CHAR)
  880.       ITERATE
  881.     END                              /* IF LEFT(STRIP(line),2) = '//' THEN DO */
  882.     ELSE IF comment & POS('*/',line) = 0 THEN DO
  883.       line = changestr(line,'°amp; < >','& < >')
  884.       line = changestr(line,'&','°')
  885.       CALL LINEOUT docFile, changestr(line,NLS_CHAR_ESC,NLS_CHAR)
  886.       ITERATE
  887.     END
  888.     ELSE IF comment THEN DO
  889.       comment = 0
  890.       line = changestr(line,'°amp; < >','& < >')
  891.       line = changestr(line,'&','°')
  892.       CALL LINEOUT docFile, changestr(line,NLS_CHAR_ESC,NLS_CHAR)
  893.       ITERATE
  894.     END                                            /* ELSE IF comment THEN DO */
  895.     ELSE IF POS('/*',line) > 0 & POS('*/',line) = 0 THEN DO
  896.       comment = 1
  897.       line = changestr(line,'°amp; < >','& < >')
  898.       line = changestr(line,'&','°')
  899.       CALL LINEOUT docFile, changestr(line,NLS_CHAR_ESC,NLS_CHAR)
  900.       ITERATE
  901.     END            /* ELSE IF POS('/*',line) > 0 & POS('*/',line) = 0 THEN DO */
  902.     ELSE IF POS('/*',line) > 0 THEN DO
  903.       line = changestr(line,'°amp; < >','& < >')
  904.       line = changestr(line,'&','°')
  905.       CALL LINEOUT docFile, changestr(line,NLS_CHAR_ESC,NLS_CHAR)
  906.       ITERATE
  907.     END
  908.  
  909.     /* print keywords private:, protected: and public: in bold   ------------ */
  910.  
  911.     IF WORDPOS('private:',line) > 0 THEN DO
  912.       CALL LINEOUT docFile, '</PRE>'
  913.       CALL LINEOUT docFile, changestr(line,'<B>private:</B>','private:',,,1)
  914.       CALL LINEOUT docFile, '<PRE>'
  915.       ITERATE
  916.     END                            /* IF WORDPOS('private:',line) > 0 THEN DO */
  917.     IF WORDPOS('protected:',line) > 0 THEN DO
  918.       CALL LINEOUT docFile, '</PRE>'
  919.       CALL LINEOUT docFile,,
  920.                             changestr(line,'<B>protected:</B>','protected:',,,1)
  921.       CALL LINEOUT docFile, '<PRE>'
  922.       ITERATE
  923.     END                          /* IF WORDPOS('protected:',line) > 0 THEN DO */
  924.     IF WORDPOS('public:',line) > 0 THEN DO
  925.       CALL LINEOUT docFile, '</PRE>'
  926.       CALL LINEOUT docFile, changestr(line,'<B>public:</B>','public:',,,1)
  927.       CALL LINEOUT docFile, '<PRE>'
  928.       ITERATE
  929.     END                             /* IF WORDPOS('public:',line) > 0 THEN DO */
  930.  
  931.     /* check for internal links   ------------------------------------------- */
  932.  
  933.     IF POS('(',line) > 0 THEN DO
  934.       ident = lastIdentifier(line,POS('(',line))
  935.       line  = changestr(line,'°amp; < >','& < >')
  936.       line  = changestr(line,'&','°')
  937.       ident = changestr(ident,'°amp; < >','& < >')
  938.       ident = changestr(ident,'&','°')
  939.       IF WORDPOS(SPACE(ident,0),classMember.className) > 0 THEN
  940.         DO k = WORDPOS(SPACE(ident,0),classMember.className) TO,
  941.                                                     WORDS(classMember.className)
  942.           member = WORD(classMember.className,k)
  943.           IF ABBREV(member,SPACE(ident,0)) &,
  944.                                    WORDPOS(member,doneInternalLinks) = 0 THEN DO
  945.             line = makeInternalRef(line,ident,member)
  946.             doneInternalLinks = doneInternalLinks member
  947.             LEAVE
  948.           END                /* WORDPOS(member,doneInternalLinks) = 0 THEN DO */
  949.         END       /* DO k = WORDPOS(SPACE(ident,0),classMember.className) TO, */
  950.     END                                       /* IF POS('(',line) > 0 THEN DO */
  951.       ELSE DO
  952.         line = changestr(line,'°amp; < >','& < >')
  953.         line = changestr(line,'&','°')
  954.       END                                                          /* ELSE DO */
  955.  
  956.     line = makeExternalRef(changestr(line,NLS_CHAR_ESC,NLS_CHAR))
  957.     CALL LINEOUT docFile, line
  958.   END                                    /* DO j=1 TO classInterf.className.0 */
  959.   CALL LINEOUT docFile, '</PRE>'
  960. END                                                                /* ELSE DO */
  961. CALL LINEOUT docFile, '</P><HR>'
  962. RETURN
  963.  
  964. /* -------------------------------------------------------------------------- */
  965. /* printMemberDoc: member description                                         */
  966. /* -------------------------------------------------------------------------- */
  967. printMemberDoc:
  968.  
  969. SAY MSG_MEMBER_DOC
  970.  
  971. CALL LINEOUT docFile, '<H2>'MEMBER_DOC_H2'</H2><P>'
  972. IF WORDS(classMember.className) = 0 THEN
  973.   CALL LINEOUT docFile, MEMBER_DOC_NONE '</P><HR>'
  974. ELSE
  975.   DO j=1 TO WORDS(classMember.className)
  976.     memberName = WORD(classMember.className,j)
  977.     PARSE VALUE memberName WITH memberTitle_H3 '!' .
  978.     CALL LINEOUT docFile, '<H3><A NAME="'memberName'">'memberTitle_H3 ||,
  979.                                                                   '</A></H3><P>'
  980.  
  981.     /* member definition ---------------------------------------------------- */
  982.  
  983.     indent = 0
  984.     CALL LINEOUT docFile, '<PRE>'
  985.     def = memberDef.className.memberName
  986.     DO WHILE LENGTH(def) > MAX_LINE_LENGTH
  987.       splitPos = LASTPOS(',',def,MAX_LINE_LENGTH)
  988.       IF splitPos = 0 THEN
  989.         splitPos = LASTPOS(' ',def,MAX_LINE_LENGTH)
  990.       token = changestr(SUBSTR(def,1,splitPos),'°amp; < >','& < >')
  991.       token = changestr(token,'&','°')
  992.       def   = STRIP(SUBSTR(def,splitPos+1))
  993.       CALL LINEOUT docFile, COPIES(' ',indent) makeExternalRef(token)
  994.       indent = 5
  995.     END                             /* DO WHILE LENGTH(def) > MAX_LINE_LENGTH */
  996.     def = changestr(def,'°amp; < >','& < >')
  997.     def = changestr(def,'&','°')
  998.     CALL LINEOUT docFile, COPIES(' ',indent) makeExternalRef(def)
  999.     CALL LINEOUT docFile, '</PRE></P><P>'
  1000.  
  1001.     /* member description   ------------------------------------------------- */
  1002.  
  1003.     DO k=1 TO memberDocu.className.memberName.0
  1004.       CALL LINEOUT docFile,,
  1005.             changestr(memberDocu.className.memberName.k,NLS_CHAR_ESC,NLS_CHAR)
  1006.     END                        /* DO k=1 TO memberDocu.className.memberName.0 */
  1007.     CALL LINEOUT docFile, '</P><P><A HREF="#'CLASS_INT_H2'">' ||,
  1008.                                                      CLASS_INT_REF'</A></P><HR>'
  1009.   END                               /* DO j=1 TO WORDS(classMember.className) */
  1010. RETURN
  1011.  
  1012. /* -------------------------------------------------------------------------- */
  1013. /* printTrailer: trailer for HTML-file                                        */
  1014. /* -------------------------------------------------------------------------- */
  1015. printTrailer:
  1016.  
  1017. ARG targetFile
  1018.  
  1019. IF omitTrailer THEN DO
  1020.   CALL LINEOUT targetFile, '<P>CPPDOC - (C) by Bernhard Bablok, 1996</P>'
  1021.   CALL LINEOUT targetFile, '<P>Please send comments, suggestions, bug-reports to:'
  1022.   CALL LINEOUT targetFile, '<A HREF="mailto:ua302cb@sunmail.lrz-muenchen.de">' ||,
  1023.                                                          'Bernhard Bablok</A></P>'
  1024. END
  1025. CALL LINEOUT targetFile, '</BODY>'
  1026. CALL LINEOUT targetFile, '</HTML>'
  1027. RETURN
  1028.  
  1029. /* -------------------------------------------------------------------------- */
  1030. /* updateIndexFile: add index entries                                         */
  1031. /* -------------------------------------------------------------------------- */
  1032. updateIndexFile:
  1033.  
  1034. IF indexFile = '' THEN
  1035.   RETURN
  1036.  
  1037. IF STREAM(indexFile,'C','query exists') = '' THEN DO
  1038.   CALL LINEOUT indexFile, '<!-- Class index generated by CPPDOC -->'
  1039.   CALL LINEOUT indexFile, '<HTML>'
  1040.   CALL LINEOUT indexFile, '<HEAD>'
  1041.   CALL LINEOUT indexFile, '<TITLE>'INDEX_TITLE'</TITLE>'
  1042.   CALL LINEOUT indexFile, '</HEAD>'
  1043.   CALL LINEOUT indexFile, '<BODY>'
  1044.   CALL LINEOUT indexFile, '<H1>'INDEX_H1'</H1><P><UL>'
  1045.   DO i=1 TO WORDS(externalRefsClassList)
  1046.     className = WORD(externalRefsClassList,i)
  1047.     CALL LINEOUT indexFile, '<LI><A HREF="'externalRefs.className ||,
  1048.                                                             '">'className'</A>',
  1049.                        changestr(classIndexInfo.className,NLS_CHAR_ESC,NLS_CHAR)
  1050.   END
  1051.   CALL LINEOUT indexFile, '</UL></P><HR>'
  1052.   CALL printTrailer indexFile
  1053.   CALL LINEOUT indexFile
  1054. END                   /* IF STREAM(indexFile,'C','query exists') = '' THEN DO */
  1055. ELSE DO
  1056.   CALL SysFileDelete indexFile
  1057.   DO i=1 TO indexAddBefore - 1
  1058.     IF WORDPOS(index.i._class,externalRefsClassList) = 0 THEN
  1059.       CALL LINEOUT indexFile, index.i
  1060.   END                                         /* DO i=1 TO indexAddBefore - 1 */
  1061.   DO i=1 TO WORDS(externalRefsClassList)
  1062.     className = WORD(externalRefsClassList,i)
  1063.     CALL LINEOUT indexFile, '<LI><A HREF="'externalRefs.className ||,
  1064.                                                             '">'className'</A>',
  1065.                        changestr(classIndexInfo.className,NLS_CHAR_ESC,NLS_CHAR)
  1066.   END
  1067.   DO i=indexAddBefore TO index.0
  1068.     IF WORDPOS(index.i._class,externalRefsClassList) = 0 THEN
  1069.       CALL LINEOUT indexFile, index.i
  1070.   END                                       /* DO i=indexAddBefore TO index.0 */
  1071.   CALL LINEOUT indexFile
  1072. END                                                                /* ELSE DO */
  1073. RETURN
  1074.  
  1075. /* -------------------------------------------------------------------------- */
  1076. /* usage: usage information                                                   */
  1077. /* -------------------------------------------------------------------------- */
  1078. usage:
  1079.  
  1080. SAY
  1081. SAY 'CPPDOC 1.11, (c) by Bernhard Bablok, 1996-1997'
  1082. SAY
  1083. SAY 'Usage: cppdoc [-x indexFile] [-t targetDirectory] [-rH2sdim] file [file ...]'
  1084. SAY
  1085. SAY 'Options: -r use relative links'
  1086. SAY '         -H hide private sections (sections with tag //@p)'
  1087. SAY '         -2 process twice'
  1088. SAY '         -s print source reference   -|'
  1089. SAY '         -d print class description   |- default: print all'
  1090. SAY '         -i print class interface     |'
  1091. SAY '         -m print member description -|'
  1092. EXIT 1
  1093.  
  1094. /*-------------------------------------------------------------------------
  1095.     GetOpt - parse options from REXX program command line
  1096.  
  1097.     Copyright (c) 1994 Lawrence R Buchanan.  ALL RIGHTS RESERVED.
  1098.  -------------------------------------------------------------------------*/
  1099. GetOpt: PROCEDURE EXPOSE GetOpt.
  1100.     PARSE ARG optstr
  1101.  
  1102.     i = GetOpt._optind
  1103.     IF GetOpt._sp = 1 THEN DO
  1104.         IF GetOpt._optind > GetOpt.0 | ,
  1105.            SUBSTR(GetOpt.i, 1, 1, '00'x) <> '-' | ,
  1106.            SUBSTR(GetOpt.i, 2, 1, '00'x) = '00'x THEN
  1107.             RETURN -1
  1108.         ELSE
  1109.             IF GetOpt.i =  '--' THEN DO
  1110.                 GetOpt._optind = GetOpt._optind + 1
  1111.                 RETURN -1
  1112.             END
  1113.     END
  1114.  
  1115.     c = SUBSTR(GetOpt.i, GetOpt._sp+1, 1, '00'x)
  1116.     GetOpt._optopt = c
  1117.     cp = POS(c, optstr)
  1118.  
  1119.     IF c = ':' | cp = 0 THEN DO
  1120.         IF GetOpt._opterr = 1 THEN
  1121.             SAY GetOpt._program ': illegal option --' c
  1122.         GetOpt._sp = GetOpt._sp + 1
  1123.         IF SUBSTR(GetOpt.i, GetOpt._sp+1, 1, '00'x) = '00'x THEN DO
  1124.             GetOpt._optind = GetOpt._optind + 1
  1125.             GetOpt._sp = 1
  1126.         END
  1127.         RETURN '?'
  1128.     END
  1129.  
  1130.     cp = cp + 1
  1131.     IF SUBSTR(optstr, cp, 1, '00'x) = ':' THEN DO
  1132.         IF SUBSTR(GetOpt.i, GetOpt._sp+2, 1, '00'x) <> '00'x THEN DO
  1133.             GetOpt._optarg = SUBSTR(GetOpt.i, GetOpt._sp+2)
  1134.             GetOpt._optind = GetOpt._optind + 1
  1135.         END
  1136.         ELSE DO
  1137.             GetOpt._optind = GetOpt._optind + 1
  1138.             i = GetOpt._optind
  1139.             IF GetOpt._optind > GetOpt.0 THEN DO
  1140.                 IF GetOpt._opterr = 1 THEN
  1141.                     SAY GetOpt._program ': option requires an argument --' c
  1142.                 GetOpt._sp = 1
  1143.                 RETURN '?'
  1144.             END
  1145.             ELSE DO
  1146.                 GetOpt._optarg = GetOpt.i
  1147.                 GetOpt._optind = GetOpt._optind + 1
  1148.             END
  1149.         END
  1150.  
  1151.         GetOpt._sp = 1
  1152.     END
  1153.     ELSE DO
  1154.         GetOpt._sp = GetOpt._sp + 1
  1155.         IF SUBSTR(GetOpt.i, GetOpt._sp+1, 1, '00'x) = '00'x THEN DO
  1156.             GetOpt._sp = 1
  1157.             GetOpt._optind = GetOpt._optind + 1
  1158.         END
  1159.  
  1160.         GetOpt._optarg = ''
  1161.     END
  1162.  
  1163. RETURN c
  1164. /* End of GetOpt */
  1165.  
  1166.  
  1167. /*-------------------------------------------------------------------------
  1168.     SetupArg - Parse command-line arguments and store in stem GetOpt.
  1169.  
  1170.     Copyright (c) 1994 Lawrence R Buchanan.  ALL RIGHTS RESERVED.
  1171.  -------------------------------------------------------------------------*/
  1172. SetupArg: PROCEDURE EXPOSE GetOpt.
  1173.     PARSE ARG arglist
  1174.  
  1175.     /* Initialize variables used in GetOpt subroutine. */
  1176.     GetOpt. = ''
  1177.     GetOpt._opterr = 1
  1178.     GetOpt._optind = 1
  1179.     GetOpt._sp   = 1
  1180.  
  1181.     /* Place program name in GetOpt._program. */
  1182.     PARSE SOURCE os . GetOpt._program .
  1183.     IF os = 'OS/2' THEN DO
  1184.         GetOpt._program = FILESPEC('N', GetOpt._program)
  1185.         GetOpt._program = DELSTR(GetOpt._program, LASTPOS('.', GetOpt._program))
  1186.     END
  1187.  
  1188.     /* Make sure the command-line contains an even number of
  1189.         quotation characters.  If it doesn't, I can't continue. */
  1190.     IF count('"',arglist) // 2 THEN DO
  1191.         SAY GetOpt._program ': Unbalanced quotation marks in command-line'
  1192.         EXIT 255
  1193.     END
  1194.  
  1195.     i = 0
  1196.     /* Load command-line options into GetOpt.1 through GetOpt.n. */    
  1197.     DO WHILE arglist <> ''
  1198.         i = i + 1
  1199.         PARSE VAR arglist GetOpt.i arglist
  1200.  
  1201.         /* If quoted argument, make sure we get it all from command-line. */
  1202.         IF POS('"', GetOpt.i) > 0 THEN DO
  1203.             cnt = count('"',GetOpt.i)
  1204.             PARSE VAR GetOpt.i opt '"' tmparg
  1205.             GetOpt.i = opt || STRIP(tmparg, 'T', '"')
  1206.             IF cnt = 1 THEN DO
  1207.                 PARSE VAR arglist remarg '"' arglist
  1208.                 GetOpt.i = GetOpt.i remarg
  1209.             END
  1210.         END
  1211.     END
  1212.     GetOpt.0 = i
  1213.  
  1214. RETURN GetOpt.0
  1215. /* End of SetupArg */
  1216.