sl@0
|
1 |
# checkLibraryDoc.tcl --
|
sl@0
|
2 |
#
|
sl@0
|
3 |
# This script attempts to determine what APIs exist in the source base that
|
sl@0
|
4 |
# have not been documented. By grepping through all of the doc/*.3 man
|
sl@0
|
5 |
# pages, looking for "Pkg_*" (e.g., Tcl_ or Tk_), and comparing this list
|
sl@0
|
6 |
# against the list of Pkg_ APIs found in the source (e.g., tcl8.2/*/*.[ch])
|
sl@0
|
7 |
# we create six lists:
|
sl@0
|
8 |
# 1) APIs in Source not in Docs.
|
sl@0
|
9 |
# 2) APIs in Docs not in Source.
|
sl@0
|
10 |
# 3) Internal APIs and structs.
|
sl@0
|
11 |
# 4) Misc APIs and structs that we are not documenting.
|
sl@0
|
12 |
# 5) Command APIs (e.g., Tcl_ArrayObjCmd.)
|
sl@0
|
13 |
# 6) Proc pointers (e.g., Tcl_CloseProc.)
|
sl@0
|
14 |
#
|
sl@0
|
15 |
# Note: Each list is "a best guess" approximation. If developers write
|
sl@0
|
16 |
# non-standard code, this script will produce erroneous results. Each
|
sl@0
|
17 |
# list should be carefully checked for accuracy.
|
sl@0
|
18 |
#
|
sl@0
|
19 |
# Copyright (c) 1998-1999 by Scriptics Corporation.
|
sl@0
|
20 |
# All rights reserved.
|
sl@0
|
21 |
#
|
sl@0
|
22 |
# RCS: @(#) $Id: checkLibraryDoc.tcl,v 1.7 2002/01/15 17:55:30 dgp Exp $
|
sl@0
|
23 |
|
sl@0
|
24 |
|
sl@0
|
25 |
lappend auto_path "c:/program\ files/tclpro1.2/win32-ix86/bin"
|
sl@0
|
26 |
#lappend auto_path "/home/surles/cvs/tclx8.0/tcl/unix"
|
sl@0
|
27 |
if {[catch {package require Tclx}]} {
|
sl@0
|
28 |
puts "error: could not load TclX. Please set TCL_LIBRARY."
|
sl@0
|
29 |
exit 1
|
sl@0
|
30 |
}
|
sl@0
|
31 |
|
sl@0
|
32 |
# A list of structs that are known to be undocumented.
|
sl@0
|
33 |
|
sl@0
|
34 |
set StructList {
|
sl@0
|
35 |
Tcl_AsyncHandler \
|
sl@0
|
36 |
Tcl_CallFrame \
|
sl@0
|
37 |
Tcl_Condition \
|
sl@0
|
38 |
Tcl_Encoding \
|
sl@0
|
39 |
Tcl_EncodingState \
|
sl@0
|
40 |
Tcl_EncodingType \
|
sl@0
|
41 |
Tcl_HashEntry \
|
sl@0
|
42 |
Tcl_HashSearch \
|
sl@0
|
43 |
Tcl_HashTable \
|
sl@0
|
44 |
Tcl_Mutex \
|
sl@0
|
45 |
Tcl_Pid \
|
sl@0
|
46 |
Tcl_QueuePosition \
|
sl@0
|
47 |
Tcl_ResolvedVarInfo \
|
sl@0
|
48 |
Tcl_SavedResult \
|
sl@0
|
49 |
Tcl_ThreadDataKey \
|
sl@0
|
50 |
Tcl_ThreadId \
|
sl@0
|
51 |
Tcl_Time \
|
sl@0
|
52 |
Tcl_TimerToken \
|
sl@0
|
53 |
Tcl_Token \
|
sl@0
|
54 |
Tcl_Trace \
|
sl@0
|
55 |
Tcl_Value \
|
sl@0
|
56 |
Tcl_ValueType \
|
sl@0
|
57 |
Tcl_Var \
|
sl@0
|
58 |
Tk_3DBorder \
|
sl@0
|
59 |
Tk_ArgvInfo \
|
sl@0
|
60 |
Tk_BindingTable \
|
sl@0
|
61 |
Tk_Canvas \
|
sl@0
|
62 |
Tk_CanvasTextInfo \
|
sl@0
|
63 |
Tk_ConfigSpec \
|
sl@0
|
64 |
Tk_ConfigTypes \
|
sl@0
|
65 |
Tk_Cursor \
|
sl@0
|
66 |
Tk_CustomOption \
|
sl@0
|
67 |
Tk_ErrorHandler \
|
sl@0
|
68 |
Tk_FakeWin \
|
sl@0
|
69 |
Tk_Font \
|
sl@0
|
70 |
Tk_FontMetrics \
|
sl@0
|
71 |
Tk_GeomMgr \
|
sl@0
|
72 |
Tk_Image \
|
sl@0
|
73 |
Tk_ImageMaster \
|
sl@0
|
74 |
Tk_ImageType \
|
sl@0
|
75 |
Tk_Item \
|
sl@0
|
76 |
Tk_ItemType \
|
sl@0
|
77 |
Tk_OptionSpec\
|
sl@0
|
78 |
Tk_OptionTable \
|
sl@0
|
79 |
Tk_OptionType \
|
sl@0
|
80 |
Tk_PhotoHandle \
|
sl@0
|
81 |
Tk_PhotoImageBlock \
|
sl@0
|
82 |
Tk_PhotoImageFormat \
|
sl@0
|
83 |
Tk_PostscriptInfo \
|
sl@0
|
84 |
Tk_SavedOption \
|
sl@0
|
85 |
Tk_SavedOptions \
|
sl@0
|
86 |
Tk_SegType \
|
sl@0
|
87 |
Tk_TextLayout \
|
sl@0
|
88 |
Tk_Window \
|
sl@0
|
89 |
}
|
sl@0
|
90 |
|
sl@0
|
91 |
# Misc junk that appears in the comments of the source. This just
|
sl@0
|
92 |
# allows us to filter comments that "fool" the script.
|
sl@0
|
93 |
|
sl@0
|
94 |
set CommentList {
|
sl@0
|
95 |
Tcl_Create\[Obj\]Command \
|
sl@0
|
96 |
Tcl_DecrRefCount\\n \
|
sl@0
|
97 |
Tcl_NewObj\\n \
|
sl@0
|
98 |
Tk_GetXXX \
|
sl@0
|
99 |
}
|
sl@0
|
100 |
|
sl@0
|
101 |
# Main entry point to this script.
|
sl@0
|
102 |
|
sl@0
|
103 |
proc main {} {
|
sl@0
|
104 |
global argv0
|
sl@0
|
105 |
global argv
|
sl@0
|
106 |
|
sl@0
|
107 |
set len [llength $argv]
|
sl@0
|
108 |
if {($len != 2) && ($len != 3)} {
|
sl@0
|
109 |
puts "usage: $argv0 pkgName pkgDir \[outFile\]"
|
sl@0
|
110 |
puts " pkgName == Tcl,Tk"
|
sl@0
|
111 |
puts " pkgDir == /home/surles/cvs/tcl8.2"
|
sl@0
|
112 |
exit 1
|
sl@0
|
113 |
}
|
sl@0
|
114 |
|
sl@0
|
115 |
set pkg [lindex $argv 0]
|
sl@0
|
116 |
set dir [lindex $argv 1]
|
sl@0
|
117 |
if {[llength $argv] == 3} {
|
sl@0
|
118 |
set file [open [lindex $argv 2] w]
|
sl@0
|
119 |
} else {
|
sl@0
|
120 |
set file stdout
|
sl@0
|
121 |
}
|
sl@0
|
122 |
|
sl@0
|
123 |
foreach {c d} [compare [grepCode $dir $pkg] [grepDocs $dir $pkg]] {}
|
sl@0
|
124 |
filter $c $d $dir $pkg $file
|
sl@0
|
125 |
|
sl@0
|
126 |
if {$file != "stdout"} {
|
sl@0
|
127 |
close $file
|
sl@0
|
128 |
}
|
sl@0
|
129 |
return
|
sl@0
|
130 |
}
|
sl@0
|
131 |
|
sl@0
|
132 |
# Intersect the two list and write out the sets of APIs in one
|
sl@0
|
133 |
# list that is not in the other.
|
sl@0
|
134 |
|
sl@0
|
135 |
proc compare {list1 list2} {
|
sl@0
|
136 |
set inter [intersect3 $list1 $list2]
|
sl@0
|
137 |
return [list [lindex $inter 0] [lindex $inter 2]]
|
sl@0
|
138 |
}
|
sl@0
|
139 |
|
sl@0
|
140 |
# Filter the lists into the six lists we report on. Then write
|
sl@0
|
141 |
# the results to the file.
|
sl@0
|
142 |
|
sl@0
|
143 |
proc filter {code docs dir pkg {outFile stdout}} {
|
sl@0
|
144 |
set apis {}
|
sl@0
|
145 |
|
sl@0
|
146 |
# A list of Tcl command APIs. These are not documented.
|
sl@0
|
147 |
# This list should just be verified for accuracy.
|
sl@0
|
148 |
|
sl@0
|
149 |
set cmds {}
|
sl@0
|
150 |
|
sl@0
|
151 |
# A list of proc pointer structs. These are not documented.
|
sl@0
|
152 |
# This list should just be verified for accuracy.
|
sl@0
|
153 |
|
sl@0
|
154 |
set procs {}
|
sl@0
|
155 |
|
sl@0
|
156 |
# A list of internal declarations. These are not documented.
|
sl@0
|
157 |
# This list should just be verified for accuracy.
|
sl@0
|
158 |
|
sl@0
|
159 |
set decls [grepDecl $dir $pkg]
|
sl@0
|
160 |
|
sl@0
|
161 |
# A list of misc. procedure declarations that are not documented.
|
sl@0
|
162 |
# This list should just be verified for accuracy.
|
sl@0
|
163 |
|
sl@0
|
164 |
set misc [grepMisc $dir $pkg]
|
sl@0
|
165 |
|
sl@0
|
166 |
set pat1 ".*(${pkg}_\[A-z0-9]+).*$"
|
sl@0
|
167 |
|
sl@0
|
168 |
# A list of APIs in the source, not in the docs.
|
sl@0
|
169 |
# This list should just be verified for accuracy.
|
sl@0
|
170 |
|
sl@0
|
171 |
foreach x $code {
|
sl@0
|
172 |
if {[string match *Cmd $x]} {
|
sl@0
|
173 |
if {[string match ${pkg}* $x]} {
|
sl@0
|
174 |
lappend cmds $x
|
sl@0
|
175 |
}
|
sl@0
|
176 |
} elseif {[string match *Proc $x]} {
|
sl@0
|
177 |
if {[string match ${pkg}* $x]} {
|
sl@0
|
178 |
lappend procs $x
|
sl@0
|
179 |
}
|
sl@0
|
180 |
} elseif {[lsearch -exact $decls $x] >= 0} {
|
sl@0
|
181 |
# No Op.
|
sl@0
|
182 |
} elseif {[lsearch -exact $misc $x] >= 0} {
|
sl@0
|
183 |
# No Op.
|
sl@0
|
184 |
} else {
|
sl@0
|
185 |
lappend apis $x
|
sl@0
|
186 |
}
|
sl@0
|
187 |
}
|
sl@0
|
188 |
|
sl@0
|
189 |
dump $apis "APIs in Source not in Docs." $outFile
|
sl@0
|
190 |
dump $docs "APIs in Docs not in Source." $outFile
|
sl@0
|
191 |
dump $decls "Internal APIs and structs." $outFile
|
sl@0
|
192 |
dump $misc "Misc APIs and structs that we are not documenting." $outFile
|
sl@0
|
193 |
dump $cmds "Command APIs." $outFile
|
sl@0
|
194 |
dump $procs "Proc pointers." $outFile
|
sl@0
|
195 |
return
|
sl@0
|
196 |
}
|
sl@0
|
197 |
|
sl@0
|
198 |
# Print the list of APIs if the list is not null.
|
sl@0
|
199 |
|
sl@0
|
200 |
proc dump {list title file} {
|
sl@0
|
201 |
if {$list != {}} {
|
sl@0
|
202 |
puts $file ""
|
sl@0
|
203 |
puts $file $title
|
sl@0
|
204 |
puts $file "---------------------------------------------------------"
|
sl@0
|
205 |
foreach x $list {
|
sl@0
|
206 |
puts $file $x
|
sl@0
|
207 |
}
|
sl@0
|
208 |
}
|
sl@0
|
209 |
}
|
sl@0
|
210 |
|
sl@0
|
211 |
# Grep into "dir/*/*.[ch]" looking for APIs that match $pkg_*.
|
sl@0
|
212 |
# (e.g., Tcl_Exit). Return a list of APIs.
|
sl@0
|
213 |
|
sl@0
|
214 |
proc grepCode {dir pkg} {
|
sl@0
|
215 |
set apis [myGrep "${pkg}_\.\*" "${dir}/\*/\*\.\[ch\]"]
|
sl@0
|
216 |
set pat1 ".*(${pkg}_\[A-z0-9]+).*$"
|
sl@0
|
217 |
|
sl@0
|
218 |
foreach a $apis {
|
sl@0
|
219 |
if {[regexp -- $pat1 $a main n1]} {
|
sl@0
|
220 |
set result([string trim $n1]) 1
|
sl@0
|
221 |
}
|
sl@0
|
222 |
}
|
sl@0
|
223 |
return [lsort [array names result]]
|
sl@0
|
224 |
}
|
sl@0
|
225 |
|
sl@0
|
226 |
# Grep into "dir/doc/*.3" looking for APIs that match $pkg_*.
|
sl@0
|
227 |
# (e.g., Tcl_Exit). Return a list of APIs.
|
sl@0
|
228 |
|
sl@0
|
229 |
proc grepDocs {dir pkg} {
|
sl@0
|
230 |
set apis [myGrep "\\fB${pkg}_\.\*\\fR" "${dir}/doc/\*\.3"]
|
sl@0
|
231 |
set pat1 ".*(${pkg}_\[A-z0-9]+)\\\\fR.*$"
|
sl@0
|
232 |
|
sl@0
|
233 |
foreach a $apis {
|
sl@0
|
234 |
if {[regexp -- $pat1 $a main n1]} {
|
sl@0
|
235 |
set result([string trim $n1]) 1
|
sl@0
|
236 |
}
|
sl@0
|
237 |
}
|
sl@0
|
238 |
return [lsort [array names result]]
|
sl@0
|
239 |
}
|
sl@0
|
240 |
|
sl@0
|
241 |
# Grep into "generic/pkgIntDecls.h" looking for APIs that match $pkg_*.
|
sl@0
|
242 |
# (e.g., Tcl_Export). Return a list of APIs.
|
sl@0
|
243 |
|
sl@0
|
244 |
proc grepDecl {dir pkg} {
|
sl@0
|
245 |
set file [file join $dir generic "[string tolower $pkg]IntDecls.h"]
|
sl@0
|
246 |
set apis [myGrep "^EXTERN.*\[ \t\]${pkg}_.*" $file]
|
sl@0
|
247 |
set pat1 ".*(${pkg}_\[A-z0-9]+).*$"
|
sl@0
|
248 |
|
sl@0
|
249 |
foreach a $apis {
|
sl@0
|
250 |
if {[regexp -- $pat1 $a main n1]} {
|
sl@0
|
251 |
set result([string trim $n1]) 1
|
sl@0
|
252 |
}
|
sl@0
|
253 |
}
|
sl@0
|
254 |
return [lsort [array names result]]
|
sl@0
|
255 |
}
|
sl@0
|
256 |
|
sl@0
|
257 |
# Grep into "*/*.[ch]" looking for APIs that match $pkg_Db*.
|
sl@0
|
258 |
# (e.g., Tcl_DbCkalloc). Return a list of APIs.
|
sl@0
|
259 |
|
sl@0
|
260 |
proc grepMisc {dir pkg} {
|
sl@0
|
261 |
global CommentList
|
sl@0
|
262 |
global StructList
|
sl@0
|
263 |
|
sl@0
|
264 |
set apis [myGrep "^EXTERN.*\[ \t\]${pkg}_Db.*" "${dir}/\*/\*\.\[ch\]"]
|
sl@0
|
265 |
set pat1 ".*(${pkg}_\[A-z0-9]+).*$"
|
sl@0
|
266 |
|
sl@0
|
267 |
foreach a $apis {
|
sl@0
|
268 |
if {[regexp -- $pat1 $a main n1]} {
|
sl@0
|
269 |
set dbg([string trim $n1]) 1
|
sl@0
|
270 |
}
|
sl@0
|
271 |
}
|
sl@0
|
272 |
|
sl@0
|
273 |
set result {}
|
sl@0
|
274 |
eval {lappend result} $StructList
|
sl@0
|
275 |
eval {lappend result} [lsort [array names dbg]]
|
sl@0
|
276 |
eval {lappend result} $CommentList
|
sl@0
|
277 |
return $result
|
sl@0
|
278 |
}
|
sl@0
|
279 |
|
sl@0
|
280 |
proc myGrep {searchPat globPat} {
|
sl@0
|
281 |
set result {}
|
sl@0
|
282 |
foreach file [glob -nocomplain $globPat] {
|
sl@0
|
283 |
set file [open $file r]
|
sl@0
|
284 |
set data [read $file]
|
sl@0
|
285 |
close $file
|
sl@0
|
286 |
foreach line [split $data "\n"] {
|
sl@0
|
287 |
if {[regexp "^.*${searchPat}.*\$" $line]} {
|
sl@0
|
288 |
lappend result $line
|
sl@0
|
289 |
}
|
sl@0
|
290 |
}
|
sl@0
|
291 |
}
|
sl@0
|
292 |
return $result
|
sl@0
|
293 |
}
|
sl@0
|
294 |
main
|
sl@0
|
295 |
|