source: branches/v2.9_Lars/create_docs.CMD@ 105

Last change on this file since 105 was 2, checked in by stevenhl, 8 years ago

Import sources from cwmm-full.zip dated 2005-03-21

File size: 19.9 KB
Line 
1/* Create documentation for functions */
2 call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
3 call SysLoadFuncs
4
5docInfo.=''
6
7theDir=ARG(1)
8
9IF theDir="" THEN theDir=STRIP(DIRECTORY())
10
11docdir="r:\temp"
12
13SAY "Base directory: "theDir
14SAY
15
16
17SAY "Checking C files..."
18rc=SysFileTree(theDir"\*.c", "files.", "FSO")
19
20numLines=0
21index=0 /* This index holds the number of found descriptions */
22DO a= 1 to files.0
23 drop contents
24 contents.=''
25 /* Count and read in lines of file */
26 DO WHILE LINES(files.a)
27 numLines=numLines+1
28 contents.numlines=LINEIN(files.a)
29 END
30 contents.0=numLines
31 call STREAM files.a, "C","close"
32
33 /* Now parse each source file */
34 exposeList='files. theLine numLines index docinfo. contents.'
35 call parseFile a
36END
37
38
39IF files.0\=0 THEN DO
40 result._C=files.0
41 result._CLines=numLines
42END
43ELSE DO
44 result._C=0
45 result._CLines=0
46END
47
48
49
50SAY ""
51SAY result._Clines||" lines in "||result._c||" C files"
52
53/*
54DO a= 1 to index
55 SAY ''
56 SAY a||': '
57 SAY 'Function: 'docinfo.a.function
58 SAY 'Line: 'docinfo.a.line
59 SAY'Desc: 'docinfo.a.desc
60 SAY ''
61 SAY 'File: 'docinfo.a.file
62END
63*/
64
65/*create docs */
66ipf=docdir||'\doc.ipf' /* The IPF file */
67res=200 /* The initial res id */
68leftWidth="30%"
69syntaxres=1 /* Res id for syntax table. To be added to base. E.G. 201 */
70remarksres=2
71returnsres=3
72exampleres=4
73overrideres=5
74usageres=6
75paramsres=10
76
77'type NUL > 'ipf
78
79/* Write IPF header */
80call writeIpfHeader ipf
81
82/* Sort the function names in the array a. */
83a.=''
84DO b= 1 to index
85 a.b=STRIP(WORD(docinfo.b.function,2))
86END
87a.0=index
88call qqsort 1, index
89
90/* Build a stem with the right order of indexes so in the document the functions are ordered */
91indStem.=''
92DO b=1 to index
93 DO c=1 to index
94 if STRIP(WORD(docinfo.c.function,2))=a.b THEN DO
95 indStem.b=c
96 LEAVE
97 END
98 END
99END
100
101/* Write function reference */
102call writeIpfFunctionRef ipf
103
104/* Footer */
105call writeIpfFooter ipf
106
107call STREAM ipf, "C","close"
108
109/* Compile the document */
110'ipfc -i 'ipf
111
112exit
113
114/**************** Procedures *********************************/
115
116writeIpfFunctionRef:
117
118 res=res+100
119 call lineout ipf, ":h1 res="||res||".Function reference"
120 call lineout ipf, ""
121
122 /* Write the function descriptions. The syntax pane is always written. The others only if
123 sufficient information is available. */
124 DO b=1 to index
125 a=indStem.b
126 res=res+100
127 call writeIpfFunction /* Write header for this function desc panel */
128 call writeIpfFuncLinks /* Add links to left pane (Syntax, remarks...) */
129 call writeIpfFuncSyntax /* Write Syntax pane */
130 call writeIpfFuncReturns /* Write return pane (lower right) */
131 call writeIpfFuncRemarks /* Write remarks pane */
132 call writeIpfFuncParams /* Write a pane for every known parameter */
133 call writeIpfFuncOverride /* Write a panel for the override information */
134 call writeIpfFuncUsage /* Write a panel for the Usage information */
135 END
136return
137
138/*********************/
139writeIpfFunction:
140 /* Write the header of the function panel */
141 call lineout ipf, ".*************** "||getFunctionName(docinfo.a.function)||"() *****************"
142 call lineout ipf, ":h2 res="||res
143 call lineout ipf, "width="leftWidth
144 call lineout ipf, "."||getFunctionName2(docinfo.a.function, docinfo.a.isSom) /* Function name */
145 call lineout ipf, ":link reftype=hd res="res+syntaxres /* Syntax will be opened initialy */
146 call lineout ipf, "auto dependent group=2."
147 call lineout ipf, ":p."
148return
149
150/*********************************/
151/* Write the links in the left panel for */
152/* this function. */
153/*********************************/
154writeIpfFuncLinks:
155 call lineout ipf, ":link reftype=hd res="||res+syntaxres||" dependent.Syntax:elink."
156 call lineout ipf, ".br"
157 if docinfo.a.numparams ><0 THEN DO
158 call lineout ipf, ":link reftype=hd res="||res+paramsres||" dependent.Parameters:elink."
159 call lineout ipf, ".br"
160 END
161 IF docinfo.a.returns >< "" THEN DO
162 call lineout ipf, ":link reftype=hd res="||res+returnsres||" dependent.Returns:elink."
163 call lineout ipf, ".br"
164 END
165 IF docinfo.a.remarks >< "" THEN DO
166 call lineout ipf, ":link reftype=hd res="||res+remarksres||" dependent.Remarks:elink."
167 call lineout ipf, ".br"
168 END
169 IF docinfo.a.override><"" THEN DO
170 call lineout ipf, ":link reftype=hd res="||res+overrideres||" dependent.How to override:elink."
171 call lineout ipf, ".br"
172 END
173 IF docinfo.a.usage><"" THEN DO
174 call lineout ipf, ":link reftype=hd res="||res+usageres||" dependent.Usage:elink."
175 call lineout ipf, ".br"
176 END
177 IF docinfo.index.example >< "" THEN DO
178 call lineout ipf, ":link reftype=hd res="||res+exampleres||" dependent.Example:elink."
179 call lineout ipf, ".br"
180 END
181return
182
183/*********************************/
184/* Write the panel for the return value */
185/*********************************/
186writeIpfFuncReturns:
187 if docinfo.a.returns="" THEN return
188
189 call lineout ipf, ":h2 res="||res+returnsres
190 call lineout ipf, "x=30%"
191 call lineout ipf, "width=70% height=35%"
192 call lineout ipf, "group=3"
193 call lineout ipf, "hide"
194 call lineout ipf, "."||getFunctionName2(docinfo.a.function, docinfo.a.isSom)||" Return value - "||WORD(docinfo.a.returns, 2)
195 call lineout ipf, ":p."
196 call lineout ipf, ":hp2."||WORD(docinfo.a.returns, 2)||":ehp2. ("||WORD(docinfo.a.returns, 1)||") - returns"
197 call lineout ipf, ":p."
198 call lineout ipf, wrapString(SUBWORD(docinfo.a.returns, 3))
199return
200
201/*****************/
202writeIpfFuncOverride:
203 if docinfo.a.override="" THEN return
204
205 call lineout ipf, ":h2 res="||res+overrideres
206 call lineout ipf, "x=30%"
207 call lineout ipf, "width=70%"
208 call lineout ipf, "group=2"
209 call lineout ipf, "hide"
210 call lineout ipf, "."||getFunctionName2(docinfo.a.function, docinfo.a.isSom)||" - How to override"
211 call lineout ipf, ":p."
212 call lineout ipf, wrapString(docinfo.a.override)
213
214return
215
216/*****************/
217writeIpfFuncUsage:
218 if docinfo.a.usage="" THEN return
219
220 call lineout ipf, ":h2 res="||res+usageres
221 call lineout ipf, "x=30%"
222 call lineout ipf, "width=70%"
223 call lineout ipf, "group=2"
224 call lineout ipf, "hide"
225 call lineout ipf, "."||getFunctionName2(docinfo.a.function, docinfo.a.isSom)||" - Usage"
226 call lineout ipf, ":p."
227 call lineout ipf, wrapString(docinfo.a.usage)
228
229return
230
231/*****************/
232writeIpfFuncParams:
233 if docinfo.a.numparams=0 THEN return /* No params given */
234
235 /* Write big parameter panel */
236 call lineout ipf, ":h2 res="||res+paramsres
237 call lineout ipf, "x=30%"
238 call lineout ipf, "width=70%"
239 call lineout ipf, "group=2"
240 call lineout ipf, "hide"
241 call lineout ipf, "."||getFunctionName2(docinfo.a.function, docinfo.a.isSom)||" - Parameters"
242 call lineout ipf, ":p."
243 DO parms = 1 to docinfo.a.numparams
244 pindex='param'||parms
245 call lineout ipf, ":hp2."||WORD(docinfo.a.pindex, 2)||":ehp2. ("||WORD(docinfo.a.pindex, 1)||") - "||WORD(docinfo.a.pindex, 3)
246 call lineout ipf, ":p."
247 call lineout ipf, ":lm margin=5."
248 call lineout ipf, wrapString(SUBWORD(docinfo.a.pindex, 4))
249 call lineout ipf, ":lm margin=1."
250 call lineout ipf, ":p."
251 END
252 call lineout ipf, "" /* Space to make source readable */
253
254 /* Write small panel (lower right) for every parameter */
255 DO parms = 1 to docinfo.a.numparams
256 pindex='param'||parms
257 call lineout ipf, ":h2 res="||res+paramsres+parms
258 call lineout ipf, "x=30%"
259 call lineout ipf, "width=70% height=35%"
260 call lineout ipf, "group=3"
261 call lineout ipf, "hide"
262 call lineout ipf, "."||getFunctionName2(docinfo.a.function, docinfo.a.isSom)||" Parameter - "||WORD(docinfo.a.pindex, 2)
263 call lineout ipf, ":p."
264 call lineout ipf, ":hp2."||WORD(docinfo.a.pindex, 2)||":ehp2. ("||WORD(docinfo.a.pindex, 1)||") - "||WORD(docinfo.a.pindex, 3)
265 call lineout ipf, ":p."
266 call lineout ipf, wrapString(SUBWORD(docinfo.a.pindex, 4))
267 END
268return
269
270/*****************************/
271/* Write the Remarks panel */
272/*****************************/
273writeIpfFuncRemarks:
274 if docinfo.a.remarks="" THEN return
275
276 call lineout ipf, ":h2 res="||res+remarksres
277 call lineout ipf, "x=30%"
278 call lineout ipf, "width=70%"
279 call lineout ipf, "group=2"
280 call lineout ipf, "hide"
281 call lineout ipf, "."||getFunctionName2(docinfo.a.function, docinfo.a.isSom)||" - Remarks"
282 call lineout ipf, ":p."
283 call lineout ipf, wrapString(docinfo.a.remarks)
284
285return
286
287/*****************/
288writeIpfFuncSyntax:
289 call lineout ipf, ""
290 call lineout ipf, ":h2 res="||res+syntaxres
291 call lineout ipf, "x=30%"
292 call lineout ipf, "width=70%"
293 call lineout ipf, "group=2"
294 call lineout ipf, "hide"
295 call lineout ipf, "."||getFunctionName2(docinfo.a.function, docinfo.a.isSom)||" - Syntax"
296 call lineout ipf, ":p."
297 call lineout ipf, wrapString(docinfo.a.desc)
298 call lineout ipf, ":nt."
299 call lineout ipf, "This function can be found in the source file :hp2."||FILESPEC("name", docinfo.a.file) ||":ehp2.."
300 call lineout ipf, ":ent."
301 call lineout ipf, ":xmp."
302 call lineout ipf, ""
303 call lineout ipf, ":parml compact tsize=25 break=none."
304 /* Check if parameters are given. If yes print them and provide a link in the syntax panel */
305 allParams=''
306 IF docinfo.a.numparams >< 0 THEN DO
307 DO parms = 1 to docinfo.a.numparams
308 pindex='param'||parms
309 allParams=allParams||":pt."||WORD(docinfo.a.pindex, 1)||":pd.:link reftype=hd res="||res+paramsres+parms||" dependent."WORD(docinfo.a.pindex, 2 )":elink.;"
310 END
311 END
312 /* Check if return info is given. If yes provide a link on syntax panel */
313 IF docinfo.a.returns >< "" THEN DO
314 allParams=allParams||":pt."||WORD(docinfo.a.returns, 1)||":pd.:link reftype=hd res="||res+returnsres||" dependent."WORD(docinfo.a.returns, 2 )":elink.;"
315 theString=WORD(docinfo.a.returns,2)||" = "||removeTypesFromFunc(SUBWORD(docinfo.a.function,2))||';'
316 END /* docinfo.a.returns */
317 ELSE
318 theString=removeTypesFromFunc(SUBWORD(docinfo.a.function,2))||';'
319 call lineout ipf, allParams
320 call lineout ipf, ":eparml."
321 thePos=1
322 tabPos=1
323 /* Split function in lines */
324 DO WHILE thePos >< 0
325 theString=STRIP(SUBSTR(theString, thePos))
326 thePos=POS(',' , theString)
327 if thePos >< 0 THEN DO
328 if tabPos=1 then DO
329 call lineout ipf, LEFT(theString, thePos)
330 tabPos=POS('(' , theString)
331 END
332 ELSE
333 call lineout ipf, COPIES(' ',tabPos)||LEFT(theString, thePos)
334 thePos=thePos+1
335 END
336 ELSE
337 call lineout ipf, COPIES(' ',tabPos)||theString
338 END
339 call lineout ipf, ":exmp."
340 call lineout ipf, ""
341return
342
343/***************************/
344removeTypesFromFunc: procedure
345 theString=SPACE(ARG(1))
346
347 /* Make sure there's always a space after '(' and ',' */
348 thePos=POS('(', theString)
349 theString=INSERT(' ', theString, thePos)
350 thePos2=POS(' ' , theString, thePos+3)
351 /* Remove '*' in front of somSelf if any */
352 tmpString=STRIP(subStr(theString, thePos2))
353 IF LEFT(tmpString, 1)='*' THEN
354 tmpString=RIGHT(tmpString, LENGTH(tmpString)-1)
355 theString=LEFT(theString, thePos)||STRIP(tmpString)
356 thePos=POS(',' , theString)
357 DO while thePos >< 0
358 theString=INSERT(' ', theString, thePos)
359 thePos2=POS(' ' , theString, thePos+3)
360 theString=LEFT(theString, thePos)||STRIP(subStr(theString, thePos2))
361 thePos=POS(',', theString, thePos+1)
362 END
363
364return theString
365
366/***************************/
367writeIpfHeader: procedure expose res
368ipf=ARG(1)
369 call lineout ipf, ":userdoc."
370 call lineout ipf, ""
371 call lineout ipf, ":docprof."
372 call lineout ipf, ""
373 call lineout ipf, ":title.Function reference"
374 call lineout ipf, ""
375 call lineout ipf, ":h1 res=100.Introduction"
376 call lineout ipf, ":p."
377 call lineout ipf, "To be written..."
378return
379
380writeIpfFooter:
381 /* Footer */
382 call lineout ARG(1), ":euserdoc."
383return
384
385/**************************/
386
387/*******************************/
388/* Strip the parameter list from the */
389/* function and return only the name */
390/* */
391/* During file parsing the whole */
392/* function declaration was read in */
393/*******************************/
394getFunctionName: procedure
395 func=ARG(1)
396 thePos=POS('(', func)
397 func=LEFT(func,thePos-1)
398
399return WORD(func,WORDS(func))
400
401/*******************************/
402/* Strip the parameter list from the */
403/* function and return only the name */
404/* */
405/* During file parsing the whole */
406/* function declaration was read in */
407/*******************************/
408getFunctionName2: procedure
409 func=ARG(1)
410 thePos=POS('(', func)
411 func=LEFT(func,thePos-1)
412 func=WORD(func,WORDS(func))
413 IF ARG(2)="YES" THEN
414 return RIGHT(func, LENGTH(func)-1)
415 ELSE
416 return func
417
418/***************************************************************/
419
420/*******************************/
421/* Parse the contents of the source */
422/* file. This means finding comments */
423/* containing function descriptions. */
424/*******************************/
425parseFile: procedure expose (exposelist)
426
427a=ARG(1)
428 curline=0
429 DO while curline <= contents.0
430 curline=curline+1
431 tempLine=STRIP(contents.curline)
432 if LENGTH(templine)<5 then iterate
433
434 if LEFT(tempLine, 4)="/*!*" then do
435 /* Comment with function description found. Now parse it. */
436 call parseComment a
437 END
438 END
439return
440
441/*******************************/
442/* Parse the whole comment block */
443/* with information */
444/*******************************/
445parseComment:
446 index=index+1
447 docinfo.index.file=STRIP(files.a)
448 docinfo.index.remarks=""
449 docinfo.index.returns=""
450 docinfo.index.example=""
451 docinfo.index.numparams=0
452 docinfo.index.override=""
453 docinfo.index.usage=""
454 DO WHILE curline<=contents.0
455 curline=curline+1
456 theLine=STRIP(contents.curline)
457 IF POS("@@",theLine) ><0 THEN call parseEntry /* Found a parameter */
458
459 IF LEFT(STRIP(theLine), 5)="/*!!*" THEN DO
460 /* End of comment. Get function name. */
461 docinfo.index.line=curline+1 /* Line of function */
462 docinfo.index.function=getCompleteFunction()
463 return
464 END
465 END
466return
467
468/********************************/
469/* Read lines until a '{' is found. */
470/* This means reading in a function */
471/* declaration. */
472/* */
473/* */
474/* */
475/********************************/
476
477getCompleteFunction:
478 theLine= ""
479 DO WHILE curline<=contents.0
480 curLine=curLine+1
481 theLine=theLine||STRIP(contents.curline)
482 IF POS("{",theLine) ><0 THEN LEAVE
483 END
484 theLine=STRIP(TRANSLATE(theLine,' ','{'))
485 /* Ok, at this point we have the whole function declaration including the parameters */
486 /* Check if we have a SOM function */
487 IF POS("SOMLINK", theLine) >< 0 THEN DO
488 /* Mark as a SOM function */
489 docinfo.index.isSom="YES"
490 /* Strip SOMLINK and SOM_Scope and the prefix */
491 thePos=POS('_', SUBWORD(theLine, 4))
492 theLine=WORD(theLine, 2)||" "||substr(SUBWORD(theLine,4), thePos)
493
494 END
495return theLine
496
497/*******************************/
498/* Parse entries starting with @@ in */
499/* comment block. */
500/*******************************/
501parseEntry:
502 entry=stripCommentChars(theLine)
503 SELECT
504 WHEN entry="@@DESC" THEN DO
505 /* Description */
506 docinfo.index.desc=readEntryContents()
507 END
508 WHEN entry="@@REMARKS" THEN DO
509 /* Remarks */
510 docinfo.index.remarks=readEntryContents()
511 END
512 WHEN entry="@@RETURNS" THEN DO
513 /* Return value */
514 docinfo.index.returns=readEntryContents()
515 END
516 WHEN entry="@@EXAMPLE" THEN DO
517 /* Example */
518 docinfo.index.example=readEntryContents()
519 END
520 WHEN entry="@@OVERRIDE" THEN DO
521 /* Override of a SOM method */
522 docinfo.index.override=readEntryContents()
523 END
524 WHEN entry="@@USAGE" THEN DO
525 /* Usage of a SOM method */
526 docinfo.index.usage=readEntryContents()
527 END
528 WHEN LEFT(entry, 7)="@@PARAM" THEN DO
529 docinfo.index.numparams=docinfo.index.numparams+1
530 parm='param'||docinfo.index.numparams
531 docinfo.index.parm=readEntryContents()
532 END
533 OTHERWISE
534 NOP
535 END
536return ""
537
538/************************************/
539/* Read the text associated with a known */
540/* entry. */
541/* Reading takes place until another entry */
542/* is found or the comment ends. */
543/************************************/
544readEntryContents:
545 theEntry=""
546 DO WHILE curline<=contents.0
547 curLine=curLine+1
548 theLine=STRIP(contents.curline)
549 IF POS("@@",theLine) ><0 THEN DO
550 curline=curline-1
551 return theEntry
552 END
553 IF LEFT(STRIP(theLine), 5)="/*!!*" THEN return theEntry
554 /* SAY '!!'||stripCommentChars(theLine)||'!!' */
555
556 if TRANSLATE(stripCommentChars(theLine))=":P." THEN DO
557 theEntry=theEntry||stripCommentChars(theLine)
558 END
559 ELSE DO
560 IF LENGTH(theEntry)>3 THEN DO
561 IF TRANSLATE(RIGHT(theEntry,3))=":P." THEN
562 theEntry=theEntry||stripCommentChars(theLine)
563 ELSE
564 theEntry=theEntry||' '||stripCommentChars(theLine)
565 END
566 ELSE DO
567 theEntry=theEntry||' '||stripCommentChars(theLine)
568 END
569
570 END
571 theEntry=STRIP(theEntry)
572/*SAY '%%'||theEntry||'%%'*/
573 END
574return theEntry
575
576/********************************/
577/* Remove starting and ending */
578/* comment chars from arg. */
579/********************************/
580stripCommentChars:
581 theString=STRIP(SUBSTR(ARG(1),3))
582return STRIP(LEFT(theString, LENGTH(theString)-2))
583
584
585/********************************/
586/* Wrap a string over several lines by */
587/* inserting '0d'x'0a'x. */
588/********************************/
589wrapString:
590
591inString=ARG(1)
592numLines=TRUNC(LENGTH(inString)/80)
593DO widx = 1 to numlines
594 thePos=POS(' ',inString ,widx*80)
595 if thePos=0 THEN return inString
596 inString=INSERT('0d'x'0a'x, inString, thePos)
597END
598return inString
599
600
601
602
603
604
605
606 /* ------------------------------------------------------------------ */
607/* Author: Ruediger Wilke */
608 /* function: quick sort routine */
609 /* */
610 /* call: QuickSort first_element, last_element */
611 /* */
612 /* returns: nothing */
613 /* */
614 /* notes: You must save the elements to sort in the stem "a." */
615 /* a.0 must contain the number of elements in the stem. */
616 /* */
617 /* */
618 qqsort: procedure expose a.
619
620 arg lf, re
621
622 if re -lf < 9 then
623 do lf = lf to re -1
624
625 m = lf
626
627 do j = lf +1 to re
628 if a.j << a.m then /* v2.80 */
629 m = j
630 end /* j = lf +1 to re */
631
632 t = a.m; a.m = a.lf; a.lf = t
633
634 end /* lf = lf to re -1 */
635 else
636 do
637 i = lf
638 j = re
639 k = (lf + re)%2
640 t = a.k
641
642 do until i > j
643
644 do while a.i << t /* v2.80 */
645 i = i + 1
646 end /* while a.i << t */
647
648 do while a.j >> t /* v2.80 */
649 j = j - 1
650 end /* while a.j >> t */
651
652 if i <= j then
653 do
654 xchg = a.i
655 a.i = a.j
656 a.j = xchg
657 i = i + 1
658 j = j - 1
659 end /* if i <= j then */
660
661 end /* until i > j */
662
663 call qqsort lf, j
664 call qqsort i, re
665 end /* else */
666
667 return
668
669
670
671
672
Note: See TracBrowser for help on using the repository browser.