home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / packages / tegra.el < prev    next >
Encoding:
Text File  |  1990-07-22  |  14.8 KB  |  530 lines

  1. ;From ark1!nap1!ames!sun-barr!lll-winken!uunet!bu-cs!mirror!ssi3b1!shyoon!tegra!vail Mon Nov  6 13:11:19 1989
  2. ;Article 649 of gnu.emacs
  3. ;Path: ark1!nap1!ames!sun-barr!lll-winken!uunet!bu-cs!mirror!ssi3b1!shyoon!tegra!vail
  4. ;From vail@tegra.UUCP (Johnathan Vail)
  5. ;Newsgroups: gnu.emacs
  6. ;Subject: Re: Automatic header creation and maintenance
  7. ;Message-ID: <814@atlas.tegra.UUCP>
  8. ;Date: 3 Nov 89 15:46:49 GMT
  9. ;References: <m0gMOq1-0000F7C@fire.indetech.com>
  10. ;Distribution: gnu
  11. ;Organization: Tegra-Varityper, Inc., Billerica, MA
  12. ;Lines: 515
  13. ;In-reply-to: lrs@indetech.com's message of 1 Nov 89 17:33:00 GMT
  14. ;
  15. ;In article <m0gMOq1-0000F7C@fire.indetech.com> lrs@indetech.com (Lynn Slater) writes:
  16. ;
  17. ;   Enclosed is code to automatically create and maintain file headers.  This
  18. ;   code is cleaner and mush more easily customized than any of my previous
  19. ;   header postings.
  20. ;
  21. ;   I have found file headers to be very valuable in project development. I
  22. ;   always know who has been where and how many times they were there. Most
  23. ;
  24. ;   ===============================================================
  25. ;   Lynn Slater -- lrs@indetech.com or {sun, ames, pacbell}!indetech!lrs
  26. ;
  27. ;Here is a set of routines that I have hacked for file and C function
  28. ;headers in my company's format.  It will take some hacking to change
  29. ;to whatever format you use but none-the-less may be useful.
  30. ;In particular, my functions provide:
  31. ;
  32. ;    File headers that use etags to find the global and local
  33. ;        functions defined.
  34. ;
  35. ;    C Function header that lists the functions used.
  36. ;
  37. ;    A quick little revision history inserterer
  38. ;
  39. ;Anyway, this represents a learning curve for me so please forgive the
  40. ;crocks...
  41. ;
  42. ;"Well they say that I'm weird and disinfectant is the only thing that I drink.
  43. ;But cleanliness of the soul is more important don't you think?" -- R Hitchcock
  44. ; _____
  45. ;|     | Johnathan Vail | tegra!N1DXG@ulowell.edu
  46. ;|Tegra| (508) 663-7435 | N1DXG@145.110-,145.270-,444.2+,448.625-
  47. ; -----
  48.  
  49. ;;;
  50. ;;;
  51. ;;;    tegra.el
  52. ;;;
  53. ;;;    This file contains Tegra-Varityper specific code documenting and
  54. ;;;    formatting functions.
  55. ;;;
  56. ;;;    Written by Johnathan Vail, Tegra Inc.
  57. ;;;
  58. ;;;    HISTORY:
  59. ;;;     5 Sep 1989 JV    - make variables appear for user change
  60. ;;;    17 Aug 1989 JV    - Add tegra-update-header
  61. ;;;    17 Aug 1989 JV    - fix etags file creation
  62. ;;;    22 Jun 1989 JV    - add iteration to loops and add purecopy
  63. ;;;    21 Jun 1989 JV    - New standards from NAD
  64. ;;;    28 Mar 1989 JV    - make real variables, add to public gnu
  65. ;;;    17 Feb 1989 JV    - add "smart" header functions/combine into tegra.el
  66. ;;;    24 Jan 1989 JV    - Added tegra-new-function
  67. ;;;     3 Jan 1989 JV    - Rewrote to Tegra-ish form
  68. ;;;     Original date routines: Constantine Rasmussen, Dec 27, 1988
  69. ;;;
  70. ;;;    BUGS:  (No no, they're features!)
  71. ;;;
  72. ;;;    * Macros and parenthesis in comments sometimes look like C functions
  73. ;;;
  74. ;;;    * forward-list and backward-list assume that we
  75. ;;;        are in C mode to properly move around `{' and `}'
  76. ;;;
  77. ;;;
  78.  
  79.  
  80.  
  81. ;;; This is, of course, user's choice
  82. ;;
  83. ;;   C-Ct   Insert timestamp like this: 22 Feb 1989 JV    -
  84. ;;   C-Cd   Will insert at point a Tegra header with most fields filled
  85. ;;   C-Cn   Insert at point a blank Tegra header
  86. ;;   C-Cl   Insert at point functions used in following C function
  87. ;;   C-Ch   Insert at point a Tegra source file (module) header, filled out
  88. ;;   C-cu   Update file header.
  89. ;;;
  90. (global-set-key "\C-ct" 'insert-user-datestamp)
  91. (global-set-key "\C-cd" 'tegra-document-function)
  92. (global-set-key "\C-cn" 'tegra-new-function)
  93. (global-set-key "\C-cl" 'list-functions-used)
  94. (global-set-key "\C-ch" 'tegra-document-header)
  95. (global-set-key "\C-cu" 'tegra-update-header)
  96.  
  97.  
  98.  
  99. (defconst  C-func-regexp "[a-zA-Z0-9_]+\\([ \t\n]*\(\\)"
  100.   "Used to look for a C function")
  101.  
  102. (defvar tegra-fluff t
  103.   "*Insert optional fields in headers if non-nil")
  104.  
  105.  
  106. ;;
  107. ;;  This defines the things that look like functions but really aren't
  108. ;;  as well as the functions that we don't want to see listed.
  109. ;;
  110.  
  111. (defvar tegra-null-functions
  112.       (quote ("if" "while" "return" "for" "switch"
  113.  
  114. ;;  Here are the functions that we don't want to know about:
  115. ;;  Mostly these are library I/O functions
  116.  
  117.           "printf" "sprintf" "strlen"
  118.           "lcd_clr" "lcd_disp" "lcd_puts" "lcd4_puts" "kpd_getc"
  119.           ))
  120.       "*List of functions that should not be on list of functions used")
  121.  
  122.  
  123.  
  124. ;;
  125. ;;  This function inserts at point all of the functions that are used in
  126. ;;  the following C function.  Each function is listed on a separate line
  127. ;;  with a `*' on the left.
  128. ;;
  129.  
  130. (defun list-functions-used ()
  131.   "Generate a list of C functions used in the current function"
  132.  
  133.   (interactive)
  134.   (let (function-list)
  135.     (save-excursion
  136.       (save-restriction
  137.     (skip-chars-forward "^{")
  138.     (beginning-of-line)
  139.     (forward-list)
  140.     (let ((end (point))) 
  141.       (backward-list)
  142.       (narrow-to-region (point) end)
  143.  
  144.       (setq function-list (find-C-functions)))))
  145.     (insert-functions-used function-list)))
  146.  
  147.  
  148.  
  149. ;;
  150. ;;  This guy does the work of actually doing the inserting
  151. ;;
  152.  
  153. (defun insert-functions-used (functions)
  154.   (cond ((null functions) nil)
  155.     (t (insert "*\t" (car functions) "\n")
  156.        (insert-functions-used (cdr functions)))))
  157.  
  158.  
  159.  
  160. ;;
  161. ;;  Return a list of functions used, sorted alphabetically and ignoring
  162. ;;  most library functions.
  163. ;;
  164. ;;    22 Jun 1989 JV    - made iterative
  165. ;;
  166.  
  167. (defun find-C-functions ()
  168.   (let (functions)
  169.     (setq functions nil)
  170.     (while (re-search-forward C-func-regexp nil t)
  171.       (setq functions
  172.         (sort-add-to-list (buffer-substring (match-beginning 0)
  173.                         (match-beginning 1))
  174.                   functions)))
  175.     functions))
  176.  
  177. ;  (cond ((re-search-forward C-func-regexp nil t)
  178. ;     (sort-add-to-list (buffer-substring (match-beginning 0) (match-beginning 1))
  179. ;               (find-C-functions)))
  180. ;    (t nil)))
  181.  
  182.  
  183.  
  184. ;;
  185. ;;  Add to the list, insertion sort
  186. ;;
  187. ;;  If the thing is on our *hit list then don't add it
  188. ;;  If list is empty then return a list of thing
  189. ;;  If the thing is already in list then don't add it again
  190. ;;  If thing comes before whats at the beginning of the list then add thing
  191. ;;  otherwise cdr down the list...
  192. ;;
  193.  
  194. (defun sort-add-to-list (thing list)
  195.   (cond ((string-memberp thing tegra-null-functions) list)
  196.     ((null list) (cons thing nil))
  197.     ((string-equal thing (car list)) list)
  198.     ((string-lessp thing (car list)) (cons thing list))
  199.     (t (cons (car list) (sort-add-to-list thing (cdr list))))))
  200.  
  201.  
  202.  
  203. ;;
  204. ;;  I couldn't find a member function for strings anywhere else...
  205. ;;
  206.  
  207. (defun string-memberp (thing list)
  208.   (cond ((null list) nil)
  209.     ((string-equal thing (car list)) t)
  210.     (t (string-memberp thing (cdr list)))))
  211.  
  212.  
  213.  
  214. ;;
  215. ;;  Take a string and insert the lines in the string as a header comment,
  216. ;;  with a star on the left margin and a single tab before the text.
  217. ;;
  218.  
  219. (defun insert-stared-lines (text)
  220.   (cond ((string-equal text "") "")
  221.     ((string-match (purecopy "[ \t\n]*\\(.*\\)\n") text)
  222.      (insert (format "*\t%s\n"
  223.              (substring text (match-beginning 1) (match-end 1))))
  224.      (insert-stared-lines (substring text (match-end 0) nil)))
  225.     (t (string-match (purecopy "[ \t]*\\(.*\\)$") text)
  226.        (insert (format "*\t%s\n"
  227.                (substring text (match-beginning 1) (match-end 1)))))))
  228.  
  229.  
  230.  
  231.  
  232. ;;
  233. ;;  This function will look for the next C function, grab all the relevent data
  234. ;;  for the header fields and then call tegra-new-function with that data
  235. ;;
  236. ;;    23 Feb 1989 JV    - Add input field
  237. ;;
  238.  
  239. (defun tegra-document-function ()
  240. "Create a new header in Tegra format and fill out as many fields as we can"
  241.  
  242.   (interactive)
  243.  
  244.   (save-excursion
  245.     (let (name synopsis input functions)
  246.       (save-excursion
  247.     (if (re-search-forward
  248.          (purecopy "^[ \t]*[a-zA-Z][a-zA-Z0-9*_ \t]*\(\\(\\([ \t]*\\)[^)]*\\)\)[^{]*")
  249.          nil t)
  250.         ()
  251.       (error "No function found to document!"))
  252.     (setq synopsis (buffer-substring (match-beginning 0) (match-end 0)))
  253.     (if (eq (match-end 1) (match-end 2))
  254.         ()
  255.       (setq input (buffer-substring (match-end 2) (match-end 1))))
  256.     (string-match C-func-regexp synopsis)
  257.     (setq name (substring synopsis (match-beginning 0) (match-beginning 1)))
  258.     (forward-list)
  259.     (save-restriction
  260.       (let ((end (point))) 
  261.         (backward-list)
  262.         (narrow-to-region (point) end))
  263.       (setq functions (find-C-functions))))
  264.       (tegra-new-function (null tegra-fluff) name synopsis input functions))))
  265.        
  266.  
  267.  
  268. ;;
  269. ;;    21 Jun 1989 JV    - Created
  270. ;;
  271.  
  272. (defun tegra-document-header ()
  273. "Create a new file header in Tegra format and fill out as many fields as we can"
  274.  
  275.   (interactive)
  276.  
  277.   (save-excursion
  278.     (let (name funcs)
  279.       (setq name (file-name-nondirectory buffer-file-name))
  280.       (setq funcs (tegra-find-functions name))
  281.       (tegra-new-header (null tegra-fluff) name (cdr funcs) (car funcs)))))
  282.  
  283.  
  284. (defun tegra-update-header ()
  285. "Update the Functions Defined: field in a Tegra file header"
  286.  
  287.   (interactive)
  288.  
  289.   (save-excursion
  290.     (let (name funcs start)
  291.       (setq name (file-name-nondirectory buffer-file-name))
  292.       (setq funcs (tegra-find-functions name))
  293.       (goto-char 0)
  294.       (re-search-forward "^\\* Functions Defined:")
  295.       (beginning-of-line)
  296.       (setq start (point))        ; start of functions region
  297.       (forward-line 1)
  298.       (if (re-search-forward "^\\*\\( [A-Z][a-z ]*:\\)\\|\\(\\*-\\*+\\)")
  299.       (progn
  300.         (beginning-of-line)
  301.         (delete-region start (point))
  302.         (tegra-insert-functions (cdr funcs) (car funcs)))
  303.     (error "No end of header found")))))
  304.  
  305.  
  306.  
  307. ;;; Usage: etags [-BFaetuwvx] [-f outfile] file ...
  308. ;;;    17 Aug 1989 JV    - fix to use a special tags file
  309.  
  310. (defun find-or-create-tags (name)
  311.   "Create a special TAGS file for the current file"
  312.   (let (tagsname)
  313.     (setq tagsname (concat name ".TAGS"))
  314.     (setq tags-file-name (concat default-directory tagsname))
  315.     (if (and (file-readable-p tags-file-name)
  316.          (file-newer-than-file-p tagsname
  317.                      (concat default-directory name)))
  318.     ()
  319.       (message (concat "Creating TAGS file " tagsname))
  320.       (shell-command (concat "etags -f " tags-file-name " " name)))
  321.     (visit-tags-table tagsname)
  322.     (visit-tags-table-buffer)
  323.     (goto-char 0)))
  324.  
  325.  
  326.  
  327. (defun tegra-find-functions (name)
  328. "Look through the tags file and find the functions defined, returning a cons of local
  329. and global lists"
  330.   (let (err beg end func local global)
  331.     (save-excursion
  332.       (find-or-create-tags name)
  333.       (save-restriction
  334.     (widen)
  335.     (if (not (search-forward name nil t))
  336.         (setq err t)
  337.       (setq beg (match-end 0))
  338.       (skip-chars-forward "^ ")
  339.       (setq end (point))
  340.       (goto-char beg)
  341.       (narrow-to-region beg end)
  342.       (while (re-search-forward "^[ \t]*[a-zA-Z][a-zA-Z0-9*_ \t]*" nil t)
  343.         (setq func (buffer-substring (match-beginning 0) (match-end 0)))
  344.         (if (string-match "^static " func)
  345.         (setq local (sort-add-to-list (substring func (match-end 0)) local))
  346.           (setq global  (sort-add-to-list func global)))))))
  347.     (if err (error (format "%s not found in tags-file" name)))
  348.     (cons local global)))
  349.  
  350.  
  351.  
  352. (setq star-line (purecopy "***********************************************************************"))
  353.  
  354.  
  355.  
  356.  
  357. ;;
  358. ;;  This function, if called by M-x inserts a mostly blank header
  359. ;;  If called from another function the fields are properly filled
  360. ;;  in.  It inserts at the current point.
  361. ;;
  362. ;;    21 Jun 1989 JV    - Change to new format
  363. ;;    23 Feb 1989 JV    - Add input field
  364. ;;
  365.  
  366.  
  367. (defun tegra-new-function (&optional no-fluff name synopsis input functions)
  368. "Insert a header for a new C function in Tegra format"
  369.  
  370.   (interactive)
  371.  
  372.   (insert
  373.    "\n\n/*++" star-line
  374.  
  375.    (format "\n*\n* %s - \n*\n" name)
  376.    "* Revision History:\n*\t"
  377.    (tegra-date (current-time-string))
  378.    " "
  379.    (initials-only (strip-aux-GCOS-info (user-full-name)))
  380.    "\t- Created\n*\n")
  381.  
  382.    
  383.   (if (null synopsis) ()
  384.     (insert "* Synopsis:\n")
  385.     (insert-stared-lines synopsis))
  386.  
  387.   (insert
  388.    "*\n"
  389.    "* Description:\n*\n")
  390.  
  391.   (if no-fluff ()
  392.     (insert "* Return Value:\n*\n"))
  393.  
  394.   (if (and (null input) no-fluff) ()
  395.     (insert "* Parameters:\n")
  396.     (if (null input) ()
  397.       (insert-stared-lines input))
  398.     (insert "*\n"))
  399.  
  400.   (if no-fluff () (insert "* Global Variables:\n*\n"))
  401.  
  402.   (if (and (null functions) no-fluff) ()
  403.     (insert "* Functions called:\n")
  404.     (if (null functions) ()
  405.       (insert-functions-used functions)
  406.       (insert "*\n")))
  407.  
  408.   (if no-fluff ()
  409.     (insert "* Side Effects:\n*\n"
  410.         "* See Also:\n*\n"
  411.         "* Technical Notes:\n*\n"
  412.         "* Known Bugs:\n*\n"
  413.         "* Example:\n*\n"))
  414.  
  415.   (insert "**--" star-line
  416.       "/\n\n"))
  417.  
  418.  
  419. ;;
  420. ;;  This function, if called by M-x inserts a mostly blank header
  421. ;;  If called from another function the fields are properly filled
  422. ;;  in.  It inserts at the current point.
  423. ;;
  424. ;;    21 Jun 1989 JV    - Create
  425. ;;
  426.  
  427.  
  428. (defun tegra-new-header (&optional no-fluff name global local)
  429. "Insert a header for a new C module in Tegra format"
  430.  
  431.   (interactive)
  432.  
  433.   (insert
  434.    "/*+*" star-line
  435.  
  436.    (format "\n* Copyright %s Tegra/Varityper, Inc "
  437.        (substring (current-time-string) -4 nil))
  438.  
  439.    (format "\n*\n* %s %s %s - \n*\n" "\%Z\%" name "\%G\%")
  440.    "* Revision History:\n*\t"
  441.    (tegra-date (current-time-string))
  442.    " "
  443.    (initials-only (strip-aux-GCOS-info (user-full-name)))
  444.    "\t- Created\n*\n")
  445.  
  446.   (insert "* Description:\n*\n")
  447.  
  448.   (if no-fluff ()
  449.     (insert "* Return Value:\n*\n"))
  450.  
  451.   (if no-fluff () (insert "* See Also:\n*\n"
  452.               "* Technical Notes:\n*\n"
  453.               "* Known Bugs:\n*\n"))
  454.  
  455.   (tegra-insert-functions global local)
  456.  
  457.  
  458.   (insert "**-*" star-line (purecopy "/\n\nstatic char *ver = \"\%W\%\t\%G\%\";\n\n"))
  459.  
  460.   (if no-fluff () (mapcar (function star-comment)
  461.               '("USEFUL MACROS *****"
  462.                 "DEFINITIONS *******"
  463.                 "EXTERNAL VARIABLES "
  464.                 "LOCAL VARIABLES ***"
  465.                 "EXTERNAL FUNCTIONS "
  466.                 "LOCAL FUNCTIONS ***"))))
  467.  
  468.  
  469.  
  470.  
  471. (defun star-comment (comment)
  472.   (insert (format (purecopy "/******* %s***********************************************/\n\n")
  473.           comment)))
  474.  
  475.  
  476. (defun tegra-insert-functions (global local)
  477.   "Insert at point the global and local functions"
  478.  
  479.   (insert "* Functions Defined:\n*\n"
  480.       "* GLOBAL\n")
  481.   (if (null global) ()
  482.     (insert-functions-used global)
  483.     (insert "*\n"))
  484.   (insert "* LOCAL\n")
  485.   (if (null local) ()
  486.     (insert-functions-used local)
  487.     (insert "*\n")))
  488.  
  489.  
  490.  
  491.  
  492.  
  493. ;;;
  494. ;;;     This is a collection of functions to get and insert the date,
  495. ;;;     user name & time.  They are useful to append logs and make notes
  496. ;;;     in sources.  Original source for some of this code:
  497. ;;;        Constantine Rasmussen
  498. ;;;
  499.  
  500. (defun insert-user-datestamp (&optional append-time)
  501.   "Args: (&OPTIONAL APPEND-TIME)
  502. Useful for timestamping in \"live\" files such as source code or logs."
  503.   (interactive "P")
  504.   (insert (tegra-date (current-time-string))
  505.       " "
  506.       (initials-only (strip-aux-GCOS-info (user-full-name))) "\t- " ))
  507.  
  508.  
  509. (defun strip-aux-GCOS-info (fullname)
  510.   (substring fullname 0 (string-match " *[-:]" fullname)))
  511.  
  512.  
  513. (defun initials-only (fullname)
  514.   (cond ((string-equal fullname "") "")
  515.     (t (concat (substring fullname 0 1)
  516.            (initials-only (substring fullname (next-word fullname) nil))))))
  517.  
  518.  
  519. (defun next-word (string)
  520.   (string-match "[^ ]* *" string)
  521.   (match-end 0))
  522.  
  523.  
  524. (defun tegra-date (time)
  525. "Returns date string in the format of  3 Jan 1989"
  526.  
  527.   (concat (substring time 8 11)
  528.       (substring time 4 8)
  529.       (substring time -4 nil)))
  530.