home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume24 / mkid2 / part04 / TUTORIAL < prev   
Text File  |  1991-10-09  |  16KB  |  434 lines

  1.  
  2. This is a program identifier database package.  These tools provide a
  3. logical extension to ctags. (which is limited in that it only stores the
  4. location of function and type *definitions*a)  The ID facility
  5. stores the locations for all uses of identifiers, pre-processor
  6. names, and numbers. (in decimal, octal or hex)
  7.  
  8. When fixing or enhancing a large program (particularly one that is
  9. unfamiliar) it is often necessary to audit the use of global
  10. data-structures in order to verify that the proposed modification will
  11. not trigger any hidden `gotchas'.  Often this entails grepping through
  12. many thousands of lines of source code spread over dozens and sometimes
  13. hundreds of source files in multiple sub-directories.  This process
  14. places a significant load on computing resources, and takes a long
  15. time.  There is even the danger that a programmer will avoid doing a
  16. complete audit due to the perceived cost--he or she will rely on memory
  17. and hope that there are no booby traps.
  18.  
  19. The id-database is most useful for maintaining large programs that
  20. consist of many source files.  The database is simply a two dimensional
  21. boolean array indexed by identifier-name and source-file-name.  For a
  22. given identifier and source-file, if the identifier occurs in the file,
  23. the boolean value is TRUE.  The database may be queried either by
  24. identifier-name or file-name.
  25.  
  26. The following types of queries supported:
  27.  
  28. * name lookup
  29.     list all the files where an identifier occurs.  The name
  30.     may be a regular expression.
  31.  
  32. * name apropos
  33.     list all the files for all identifiers that have the sub-string
  34.     name in them.  Matches are done in a case-insensitive mammer.
  35.  
  36. * name `grep'
  37.     search for an identifier in all the files where it occurs.
  38.     This is an optimized `grep' over all the sources--we only
  39.     search on files that contain the identifier.
  40.  
  41. * name edit
  42.     invoke an editor on the files where an identifier occurs,
  43.     and use the identifier as an initial search string.
  44.  
  45. * file lookup
  46.     list all identifiers that occur in a file, or list
  47.     the identifiers that are common between two files.
  48.  
  49. * non-unique names
  50.     list the names of all indentifiers whose names are non-unique
  51.     within some number of characters.  This is useful when porting
  52.     a program from a `flexnames' system to one more limited names.
  53.  
  54. * solo
  55.     list all identifiers that occur exactly once in a software
  56.     system.  This may be useful for locating identifiers that are
  57.     declared but never used, or library functions that are used
  58.     but never declared.
  59.     
  60.  
  61. The first four queries are handled by one program.  The type of query
  62. is determined by the name the program was invoked with.  The four links
  63. are lid(1) for `lookup id', aid(1) for `apropos id', gid(1) for `grep
  64. id' and eid(1) for `edit id'.  One or more identifiers may be passed on
  65. the command line.  The identifiers may be literal strings or regular
  66. expressions.  Here are some examples:
  67.  
  68. $ lid FILE
  69. FILE           extern.h {fid,gets0,getsFF,idx,init,lid,mkid,opensrc,scan-asm,scan-c}.c
  70.  
  71. $ lid FILE$
  72. AF_FILE        mkid.c
  73. AF_IDFILE      mkid.c
  74. FILE           extern.h {fid,gets0,getsFF,idx,init,lid,mkid,opensrc,scan-asm,scan-c}.c
  75. IDFILE         id.h {fid,lid,mkid}.c
  76. IdFILE         {fid,lid}.c
  77. argFILE        mkid.c
  78. gidFILE        lid.c
  79. idFILE         {init,mkid}.c
  80. inFILE         {gets0,getsFF,scan-asm,scan-c}.c
  81. openSrcFILE    extern.h {idx,mkid,opensrc}.c
  82. srcFILE        {idx,mkid,opensrc}.c
  83.  
  84. $ lid ^get
  85. get            opensrc.c
  86. getAdaId       getscan.c
  87. getAsmId       extern.h {getscan,scan-asm}.c
  88. getCId         extern.h {getscan,scan-c}.c
  89. getDirToName   extern.h {fid,lid,paths}.c
  90. getId          {idx,mkid}.c
  91. getLanguage    extern.h {getscan,idx,mkid}.c
  92. getLispId      getscan.c
  93. getPascalId    getscan.c
  94. getRoffId      getscan.c
  95. getSCCS        extern.h opensrc.c
  96. getScanner     extern.h {getscan,idx,mkid}.c
  97. getTeXId       getscan.c
  98. getTextId      getscan.c
  99. getc           {gets0,getsFF,lid,scan-asm,scan-c}.c
  100. getchar        lid.c
  101. getenv         extern.h lid.c
  102. gets           lid.c
  103. getsFF         extern.h {bitsvec,fid,getsFF,lid,mkid}.c
  104.  
  105. As you can see, when a regular expression is used, it is possible to
  106. get more than one line of output.  If you wish multiple lines to be
  107. merged into one, supply the `-m' option:
  108.  
  109. $ lid -m ^get
  110. ^get           extern.h {bitsvec,fid,gets0,getsFF,getscan,idx,lid,mkid,opensrc,paths,scan-asm,scan-c}.c
  111.  
  112. The query program searches for numbers numerically rather than
  113. textually.  Therefore you may search for multiple representations of a
  114. number.  It is best to illustrate this with examples:
  115.  
  116. $ lid -a 0x10
  117. 020            numtst.c
  118. 0x00010        numtst.c
  119. 0x0010         scan-c.c
  120. 0x10           {id,radix}.h {scan-asm,stoi}.c
  121. 16             numtst.c
  122.  
  123. The `-a' argument tells lid(1) to look for 0x10 in all radixes.  (For
  124. numbers 0 through 7, lid(1) looks for all radixes by default.  For numbers
  125. greater than 7, lid(1) only looks for the radix that the argument is
  126. supplied in.) It is also possible to restrict the search to selected
  127. radixes by supplying an argument consisting of one or more of the
  128. key-letters `o', `d', and `x' for octal decimal and hexadecimal
  129. respectively:
  130.  
  131. $ lid -o 0x10
  132. 020            numtst.c
  133.  
  134. $ lid -x 16
  135. 0x00010        numtst.c
  136. 0x0010         scan-c.c
  137. 0x10           {id,radix}.h  {scan-asm,stoi}.c
  138.  
  139. $ lid -d 020
  140. 16             numtst.c
  141.  
  142.  
  143. The grep interface behaves somewhat like the following command:
  144.  
  145. $ grep -w -n `lid TRUE`
  146.  
  147. Heres some sample output for the equivalent gid command:
  148.  
  149. $ gid TRUE
  150. bool.h:5: #define    TRUE    (0==0)
  151. lid.c:102:         case 'm': forceMerge = TRUE; break;
  152. lid.c:170:             Merging = TRUE;
  153. lid.c:204:             crunching = TRUE;
  154. lid.c:553:             hitDigits = TRUE;
  155. lid.c:787:             return TRUE;
  156. mkid.c:117:             Verbose = TRUE;
  157. mkid.c:191:                     keepLang = TRUE;
  158. scan-asm.c:79: static bool eatUnder = TRUE;
  159. scan-asm.c:80: static bool preProcess = TRUE;
  160. scan-asm.c:96:     static bool    newLine = TRUE;
  161. scan-asm.c:130:         newLine = TRUE;
  162. scan-asm.c:141:         newLine = TRUE;
  163. scan-asm.c:145:         newLine = TRUE;
  164. scan-asm.c:150:         newLine = TRUE;
  165. scan-asm.c:165:                 newLine = TRUE;
  166. scan-c.c:88: static bool eatUnder = TRUE;
  167. scan-c.c:101:     static bool    newLine = TRUE;
  168. scan-c.c:138:         newLine = TRUE;
  169. scan-c.c:199:                 newLine = TRUE;
  170. scan-c.c:205:         newLine = TRUE;
  171. scan-c.c:210:             newLine = TRUE;
  172. wmatch.c:37:             return TRUE;
  173.  
  174. Notice that each line is reported in the same format as a
  175. C-preprocessor error message.  This feature allows gid(1) lines to be
  176. digested by any program that parses error messages, such as error(1)
  177. and gnu-emacs.
  178.  
  179. If you want to edit all files that have an identifier, you may
  180. conveniently do so with eid(1):
  181.  
  182. $ eid TRUE
  183. TRUE           bool.h {lid,mkid,scan-asm,scan-c,wmatch}.c
  184. Edit? [y1-9^S/nq] 
  185.  
  186. Before the editor is invoked, you are given the lid(1) output to review
  187. and comfirm.  If you want to edit all files listed, respond with a
  188. newline or with `y'.  If you want to skip some number of files into the
  189. argument list, respond with a single digit `1' through `9' to skip that
  190. many files, or do a string-search to the first file you want with
  191. `^S<string>' or `/<string>'.  If you don't want to edit anything, type
  192. `n' to go on to the next argument you gave to eid(1) or type `q' to
  193. quit altogether.
  194.  
  195. The behavior of the editing interface is controlled by three
  196. environment variables called EIDARG, EIDLDEL, and EIDRDEL.  The best
  197. way to illustrate their use by an example.  Here is how to define them
  198. for vi(1) (using /bin/sh syntax)
  199.  
  200. EIDARG='+/%s/'    # printf(3) string for initial search-string argument
  201. EIDLDEL='\<'    # left word-delimiter
  202. EIDRDEL='\>'    # right word-delimiter
  203.  
  204. `EID[LR]DEL' are positioned around the identifier as left and right
  205. word-delimiters if your editor supports that notion.  Then the whole
  206. name-string is sprintf(3)'ed into `EIDARG' to construct the initial
  207. search-string argument to the editor.  If your editor can't digest such
  208. an argument, simply leave these variables undefined in the
  209. environment.
  210.  
  211. Some emacs users are appalled at the notion of starting up a fresh editor
  212. simply to follow an identifier.  For those who are fortunate enough to have
  213. a programmable emacs such as gnu-emacs, it is fairly simple to devise
  214. a command that invokes gid(1) and digests its output as though it were
  215. /lib/cpp error strings to be examined.  (Sorry, no such code is provided
  216. at this posting...)
  217.  
  218. Another type of query is to find all identifiers that are non-unique
  219. within some number of characters.  This is useful for finding potential
  220. portability problems when moving to a system whose compiler or linker
  221. limits the number of significant characters in a name.  The `-u<n>'
  222. argument does the trick.  Here's a list of identifiers that may yield
  223. multiply-defined errors in a symbol table that only knows about the
  224. first 7 characters:
  225.  
  226. $ lid -u7
  227. SCAN_TEX       getscan.c
  228. SCAN_TEXT      getscan.c
  229. idh_argc       id.h {init,mkid}.c
  230. idh_argo       id.h {init,mkid}.c
  231. idh_namc       id.h {fid,mkid}.c
  232. idh_namo       id.h {fid,init,lid,mkid}.c
  233. oldHashSize    mkid.c
  234. oldHashTable   mkid.c
  235.  
  236. Better yet, if you want to edit these, try
  237.  
  238. $ eid -u7
  239. ^SCAN_TE       getscan.c
  240. Edit? [y1-9^S/nq] n
  241. ^idh_arg       getscan.c id.h {init,mkid}.c
  242. Edit? [y1-9^S/nq] n
  243. ^idh_nam       {fid,getscan}.c id.h {init,lid,mkid}.c
  244. Edit? [y1-9^S/nq] n
  245. ^oldHash       {fid,getscan}.c id.h {init,lid,mkid}.c
  246. Edit? [y1-9^S/nq] n
  247.  
  248.  
  249. An additional feature of lid(1) is that pathnames are automatically
  250. adjusted for the current working directory.  Large programs such as the
  251. UNIX kernel are often partitioned into subsystems whose sources live in
  252. different directories.  What follows are several examples of the same
  253. search conducted from different points in the UNIX kernel source
  254. hierarchy:
  255.  
  256. $ cd /src/uts/m68k
  257. $ lid bdevsw
  258. bdevsw         sys/conf.h  cf/conf.c  io/bio.c  os/{fio,main,prf,sys3}.c
  259.  
  260. $ cd io
  261. $ lid bdevsw
  262. bdevsw         ../sys/conf.h  ../cf/conf.c  bio.c  ../os/{fio,main,prf,sys3}.c
  263.  
  264. $ cd ../os
  265. bdevsw         ../sys/conf.h  ../cf/conf.c  ../io/bio.c  {fio,main,prf,sys3}.c
  266.  
  267. The database is built with mkid(1).  The user supplies pathnames
  268. either on the command line or on stdin.  Here's the output of the
  269. `verbose' option to mkid(1):
  270.  
  271. $ mkid -v *.h *.c
  272. c: bitops.h
  273. c: bool.h
  274. c: extern.h
  275. c: id.h
  276. c: patchlevel.h
  277. c: radix.h
  278. c: string.h
  279. c: basename.c
  280. c: bitcount.c
  281. c: bitops.c
  282. c: bitsvec.c
  283. c: bsearch.c
  284. c: bzero.c
  285. c: document.c
  286. c: fid.c
  287. c: gets0.c
  288. c: getsFF.c
  289. c: getscan.c
  290. c: hash.c
  291. c: idx.c
  292. c: init.c
  293. c: lid.c
  294. c: mkid.c
  295. c: numtst.c
  296. c: opensrc.c
  297. c: paths.c
  298. c: scan-asm.c
  299. c: scan-c.c
  300. c: stoi.c
  301. c: tty.c
  302. c: uerror.c
  303. c: wmatch.c
  304. Compressing Hash Table...
  305. Sorting Hash Table...
  306. Writing `ID'...
  307. Names: 593, Numbers: 64, Strings: 43, Solo: 119, Total: 697
  308. Occurrances: 11.67, Load: 0.17, Probes: 1.07
  309.  
  310. Mkid(1) echoes the name of each file as it is scanned, prefixed by the
  311. name of the language it thinks the file is written in.  Mkid(1) reports
  312. how many unique names and numbers were found, how many names occurred
  313. only once, and the total for names and numbers.  It also reports the
  314. average number of occurrances for all names and numbers.  Next, there
  315. are some hash-table statistics on the load-factor and the average
  316. number of open-addressed probes.
  317.  
  318. Mkid(1) can take arguments from the command line, from stdin, or from
  319. a file.  A file full of filenames may also contain mkid options of the form
  320. -<option>.  Filenames and options appear in the file one-per-line.  Typical
  321. usage for this feature is as follows:
  322.  
  323. $ find . -name '*.[chys]' -print >IDFILES
  324. $ mkid -aIDFILES
  325.  
  326. -- or --
  327.  
  328. $ find . -name '*.[chys]' -print |mkid -
  329.  
  330. Mkid(1) stashes the filenames and relevant arguments in the database
  331. itself.  It uses these to support the ``incremental-update' option.
  332. If invoked with `-u', mkid(1) checks the modification times of all
  333. constituent files, and only re-scans those that are newer than the
  334. database itself.  It is invoked like so:
  335.  
  336. $ mkid -u
  337.  
  338. In summation, mkid(1) can get arguments from one of four places:
  339. 1) the command line, 2) a file, 3) stdin, 4) the database itself.
  340.  
  341. Mkid(1) accepts a number of scanner-specific arguments.  Generally,
  342. these are introduced with `-S<lang>' where <lang> is the name of
  343. a language, such as `c' or `asm'.  You can get a scanner-specific
  344. usage-report with `-S<lang>?'  (Of course, the `?' must be escaped
  345. to get it past the shell)
  346.  
  347. Here's scanner-usage for the assembly language scanner:
  348.  
  349. $ mkid -Sasm\?
  350. The Assembler scanner arguments take the form -Sasm<arg>, where
  351. <arg> is one of the following: (<cc> denotes one or more characters)
  352.   -c<cc> . . . . <cc> introduce(s) a comment until end-of-line.
  353.   (+|-)u . . . . (Do|Don't) strip a leading `_' from ids.
  354.   (+|-)a<cc> . . Allow <cc> in ids, and (keep|ignore) those ids.
  355.   (+|-)p . . . . (Do|Don't) handle C-preprocessor directives.
  356.   (+|-)C . . . . (Do|Don't) handle C-style comments. (/* */)
  357.  
  358. `-Sasm-c<cc>' tells the scanner what characters are used to introduce comments
  359. that extend to end-of-line.
  360.  
  361. Use `-Sasm+u' if your C compiler prepends leading underscores to external
  362. names.  This way, mkid(1) will strip leading underscores, and the name
  363. `foo' in a C source will be correctly associated with the name `_foo'
  364. in an assembler source.  If your compiler doesn't prepend leading
  365. underscores, use `-Sasm-u'.
  366.  
  367. Many assemblers allow special characters to be mixed with
  368. alpha-numerics in label, constant and register names.  Common choices
  369. are `.', `%', and `$'.  Thus, a label such as `L%123' should be scanned
  370. as one token, not broken up into the name `L' and the number 123.
  371. `-Sasm-a%.' tells the scanner to allow `%' and `.' in tokens, but to throw
  372. away tokens containing `%' or `.' `-Sasm+a%.' tells the scanner to keep such
  373. tokens and put them into the database.
  374.  
  375.  
  376. `-Sasm+p' tells the scanner to handle `#include' and `#define' lines as
  377. in C source, and `-Sasm+C' tells it to ignore C-style comments.
  378.  
  379. Here's the scanner-usage for C:
  380.  
  381. $ mkid -Sc\?
  382. The C scanner arguments take the form -Sc<arg>, where <arg>
  383. is one of the following: (<cc> denotes one or more characters)
  384.   (+|-)u . . . . (Do|Don't) strip a leading `_' from ids in strings.
  385.   -s<cc> . . . . Allow <cc> in string ids.
  386.  
  387. The `+u' argument is akin to the argument for the assembly-language
  388. scanner.  Mkid(1) keeps the contents of quoted-strings if the string
  389. contains a single valid C name and nothing else.  E.g.  mkid(1) would
  390. keep the contents of "_proc".  Such strings are interesting because
  391. they may contain symbol names that a program uses for nlist lookups.
  392. So, if your compiler prepends underscores to external symbols, use
  393. `-Sc+u' so that mkid(1) will strip them back off.
  394.  
  395. Mkid(1) normally throws away the contents of quoted strings that have
  396. anything other than a single name in them.  You can tell mkid(1) to
  397. accept additional characters in strings with `-Sc-s<cc>' where <cc> is
  398. one or more special characters.  E.g. `-Sc-s/.-:,' will include most of
  399. the strings containing pathnames that you are likely to encounter.
  400.  
  401. Another class of scanner argument allows you to associate a suffix
  402. with a language.  E.g. `-S.y=c' tells mkid(1) to use the C language
  403. scanner on all files ending with .y.  You can ask mkid(1) for the
  404. available scanners and associated suffixes like so:
  405.  
  406. $ mkid -S\?=\?
  407. .c=c, .h=c, .y=c, .s=asm, .p=pascal, .pas=pascal
  408.  
  409. Please note, mkid(1) is lying to you about its Pascal prowess!
  410. At the time of this posting, there are scanners for C and assembly
  411. language sources.  There are also stubs for Pascal, Ada and LISP.  The
  412. scanners are very fast.  The assembly language scanner knows how
  413. to throw away C-style comments as well as the traditional `comment-
  414. character-until-end-of-line' style.  In order to test new scanners,
  415. there is a scanner driver called idx(1).  Idx(1) simply calls the
  416. scanner to get identifiers one-at-a-time prints them on stdout one-per-line.
  417.  
  418. For more information, read the manual pages!
  419.  
  420. Happy Hacking,
  421. --
  422. -- Greg McGary
  423. -- P.O. Box 286
  424. -- Lincoln, MA  01773
  425. --
  426. -- 9/15/87
  427. --
  428. --    Until the end of 1987,
  429. --    Consulting to Sun's East Coast Division:
  430. --        gmcgary@ecd.sun.com
  431. --        gmcgary@suneast.uu.net
  432. --
  433. --    After that, probably consulting in Europe...
  434.